spring知識點

一、Spring概述

1.1 web項目開發中的耦合度問題

  • 在Servlet中需要調用service中的方法,則需要在Servlet類中通過new關鍵字創建Service的實例

    public interface ProductService{public List<Product> listProducts();
    }
    
    public class ProductServiceImpl1 implements ProductService{public List<Product> listProducts(){//查詢熱銷商品}
    }
    
    public class ProductServiceImpl2 implements ProductService{public List<Product> listProducts(){//查詢好評商品}
    }
    
    public class ProductListServlet extends HttpServlet{//在servlet中使用new關鍵字創建ProductServiceImpl1對象,增加了servlet和service的耦合度private ProductService productService = new ProductServiceImpl1();protected void doGet(HttpServletRequest request,HttpServletResponse response){doPost(request,response);}protected void doPost(HttpServletRequest request,HttpServletResponse response){productService.listProducts();}
    }
    
  • 在service實現類中需要調用DAO中的方法,也需要在servcie實現類通過new關鍵字創建DAO實現類對象

  • 如果使用new關鍵字創建對象:

    • 失去了面向接口編程的靈活性
    • 代碼的侵入性增強(增加了耦合度)、降低了代碼的靈活性
    • 增強項目的擴展性

1.2 面向接口編程

面向接口編程
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-p4BAd5PZ-1639493961428)(imgs/1616724645995.png)]

解決方案:在Servlet中定義Service接口的對象變量,不使用new關鍵字創建實現類對象,在servlet的實例化的時候,通過反射動態的給Service對象變量賦值。

如何實現:Spring可以做到!!!

1.3 Spring介紹

Spring是一個輕量級的控制反轉和面向切面的容器框架,用來解決企業項目開發的復雜度問題—解耦

  • 輕量級:體積小,對代碼沒有侵入性
  • 控制反轉:IoC(Inverse of Control),把創建對象的工作交由Spring完成,Spring在創建對象的時候同時可以完成對象屬性賦值(DI)
  • 面向切面:AOP(Aspect Oriented Programming)面向切面編程,可以在不改變原有業務邏輯的情況下實現對業務的增強
  • 容器:實例的容器,管理創建的對象

1.4 Spring架構

  • 官網 https://spring.io/

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-T0zDiRhQ-1639493961430)(imgs/1616728103181.png)]

  • Spring架構圖

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rXTJntXf-1639493961431)(imgs/1616728204844.png)]

1.4.1 Core Container

Spring容器組件,用于完成實例的創建和管理

  • core
  • beans 實例管理
  • context 容器上下文
1.4.2 AOP、Aspects

Spring AOP組件,實現面向切面編程

  • aop
  • aspects
1.4.3 web

Spring web組件實際指的是SpringMVC框架,實現web項目的MVC控制

  • web (Spring對web項目的支持)
  • webmvc (SpringMVC組件)
1.4.4 Data Access

Spring數據訪問組件,也是一個基于JDBC封裝的持久層框架(即使沒有mybatis,Spring也可以完成持久化操作)

  • tx
1.4.5 Test

Spring的單元測試組件,提供了Spring環境下的單元測試支持

  • test

二、Spring IoC — 基于XML

Spring IoC 容器組件,可以完成對象的創建、對象屬性賦值、對象管理

2.1 Spring框架部署(IoC)

2.1.1 創建Maven工程
  • Java
  • Web
2.1.2 添加SpringIoC依賴
  • core
  • beans
  • aop
  • expression
  • context
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.13.RELEASE</version>
</dependency>
2.1.3 創建Spring配置文件

通過配置文件"告訴"Spring容器創建什么對象,給對象屬性賦什么值

  • 在resources目錄下創建名為appicationContext.xml的文件(文件名是可以自定義的)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--  對于一個xml文件如果作為框架的配置文件,需要遵守框架的配置規則  --><!--  通常一個框架為了讓開發者能夠正確的配置,都會提供xml的規范文件(dtd\xsd)  --></beans>

2.2 SpringIoC使用

使用 SpringIoC組件創建并管理對象

2.2.1 創建一個實體類
public class Student {private String stuNum;private String stuName;private String stuGender;private int stuAge;private Date enterenceTime; //入學日期}
2.2.2 在Spring配置文件中配置實體類
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--通過bean將實體類配置給Spring進行管理,id表示實體類的唯一表示--><bean id="stu" class="com.qfedu.ioc.bean.Student"><property name="stuNum" value="10002"/><property name="stuName" value="李斯"/><property name="stuGender" value=""/><property name="stuAge" value="20"/></bean></beans>
2.2.3 初始化Spring對象工廠,獲取對象
  • ClassPathXMLApplicationContext
//1.初始化Spring容器,加載Spring配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.通過Spring容器獲取Student對象
Student student2 = (Student) context.getBean("stu");

2.3 IoC和DI

  • IoC (Inverse of Control) 控制反轉,通過Spring對象工廠完成對象的創建
  • DI (Dependency Injection)依賴注入,在Spring完成對象創建的同時依賴Spring容器完成對象屬性的賦值
2.3.1 IoC

當我們需要通過Spring對象工廠創建某個類的對象時候,需要將這個交給Spring管理——通過bean標簽配置

<!--通過bean將實體類配置給Spring進行管理,id表示實體類的唯一表示-->
<bean id="stu" class="com.qfedu.ioc.bean.Student"></bean><bean id="book" class="com.qfedu.ioc.bean.Book"></bean>
2.3.2 DI

通過Spring容器給創建的對象屬性賦值

<bean id="clazz" class="com.qfedu.ioc.bean.Clazz"></bean><!--通過bean將實體類配置給Spring進行管理,id表示實體類的唯一表示-->
<bean id="stu" class="com.qfedu.ioc.bean.Student" autowire="byName"><property name="stuNum" value="10001"/>
</bean>

2.4 DI依賴注入

2.4.1 依賴注入三種方式

Spring容器加載配置文件之后,通過反射創建類的對象,并給屬性賦值;

Spring容器通過反射實現屬性注入有三種方式:

  • set方法注入
  • 構造器注入
  • 接口注入(不常用)
2.4.2 set方法注入

在bean標簽中通過配置property標簽給屬性屬性賦值,實際上就是通過反射調用set方法完成屬性的注入

簡單類型及字符串

  • 直接通過property標簽的value屬性賦值
<!--通過bean將實體類配置給Spring進行管理,id表示實體類的唯一表示-->
<bean id="stu" class="com.qfedu.ioc.bean.Student" autowire="byName"><!--    簡單類型    --><property name="stuNum" value="10001"/><property name="stuAge" value="12"/><!--    字符串類型--><property name="weight" value="62.3"/>
</bean>

日期類型

  • 方式1:在property標簽中通過ref引用Spring容器中的一個對象
<bean id="date" class="java.util.Date"></bean><bean id="stu" class="com.qfedu.ioc.bean.Student" ><!--    日期類型--><property name="enterenceTime" ref="date"/>
</bean>
  • 方式2:在property標簽中添加子標簽bean來指定對象
<bean id="stu" class="com.qfedu.ioc.bean.Student" ><!--    日期類型--><property name="enterenceTime"><bean class="java.util.Date"/></property>
</bean>

自定義類對象屬性

  • 方式1:
<bean id="cla" class="com.qfedu.ioc.bean.Clazz"><property name="classId" value="2010"/><property name="className" value="Java2010"/>
</bean><bean id="stu" class="com.qfedu.ioc.bean.Student"><!--  自定義對象類型--><property name="clazz" ref="cla"/>
</bean>
  • 方式2
<bean id="stu" class="com.qfedu.ioc.bean.Student"><!--  自定義對象類型--><property name="clazz"><bean class="com.qfedu.ioc.bean.Clazz"><property name="classId" value="2010"/><property name="className" value="Java2010"/></bean></property>
</bean>

集合類型

  • List

    • List List中的元素是字符串或者簡單類型的封裝類
    <property name="hobbies" value="旅游,電影"/>
    
    <property name="hobbies" ><list><value>旅游</value><value>電影</value><value>Java</value></list>
    </property>
    
    • List List中的元素是對象類型
    <property name="hobbies" ><list><bean class="com.qfedu.ioc.bean.Book"/><bean class="com.qfedu.ioc.bean.Book"/><bean class="com.qfedu.ioc.bean.Book"/><bean class="com.qfedu.ioc.bean.Book"/></list>
    </property>
    
    <property name="hobbies" ><list><ref bean="book"></ref>  <!--引用容器中的備案--><ref bean="book"></ref></list>
    </property>
    
  • Set

    <property name="sets"><set><!--和list元素注入方式相同--></set>
    </property>
    
  • Map

    <property name="maps"><map><entry><key><value>k1</value></key><value>123</value></entry><entry><key><value>k2</value></key><value>456</value></entry></map>
    </property>
    
  • Properties

    <property name="properties"><props><prop key="k1">aaa</prop><prop key="k2">bbb</prop></props>
    </property>
    
2.4.3 構造器注入

簡單類型、字符串、對象

public class Student {private String stuNum;private String stuName;private String stuGender;private int stuAge;private double weight;private Date enterenceTime; //入學日期private Clazz clazz;public Student(String stuNum, String stuName, String stuGender, int stuAge, double weight, Date enterenceTime, Clazz clazz) {this.stuNum = stuNum;this.stuName = stuName;this.stuGender = stuGender;this.stuAge = stuAge;this.weight = weight;this.enterenceTime = enterenceTime;this.clazz = clazz;}
}
<bean id="date" class="java.util.Date"></bean><bean id="stu" class="com.qfedu.ioc.bean.Student"><constructor-arg index="0" value="10001"/>       <!--字符串類型--><constructor-arg index="2" value=""/><constructor-arg index="1" value="張三"/><constructor-arg index="3" value="21"/>       <!--簡單類型--><constructor-arg index="4" value="62.5"/><constructor-arg index="5" ref="date"/>       <!--對象類型--><constructor-arg index="6">                  <!--對象類型--><bean class="com.qfedu.ioc.bean.Clazz"></bean></constructor-arg>
</bean>

集合類型屬性

public class Student{private List<String> hobbies;private Set<String> sets;private Map<String,Object> maps;private Properties properties;public Student(List<String> hobbies, Set<String> sets, Map<String, Object> maps, Properties properties) {this.hobbies = hobbies;this.sets = sets;this.maps = maps;this.properties = properties;}
}
<bean id="stu1" class="com.qfedu.ioc.bean.Student"><constructor-arg index="0"><list><value>11</value><value>22</value><value>33</value></list></constructor-arg><constructor-arg index="1"><set><value>aa</value><value>bb</value><value>cc</value></set></constructor-arg><constructor-arg index="2"><map><entry><key><value>key1</value></key><value>value1</value></entry><entry><key><value>key2</value></key><value>value2</value></entry></map></constructor-arg><constructor-arg index="3"><props><prop key="k1">v1</prop><prop key="k2">v2</prop></props></constructor-arg>
</bean>

2.5 Bean的作用域

在bean標簽可以通過scope屬性指定對象的的作用域

  • scope=“singleton” 表示當前bean是單例模式(默認餓漢模式,Spring容器初始化階段就會完成此對象的創建;當在bean標簽中設置 lazy-init="true"變為懶漢模式)
  • scope=“prototype” 表示當前bean為非單例模式,每次通過Spring容器獲取此bean的對象時都會創建一個新的對象
  • 單例
<bean id="book" class="com.qfedu.ioc.bean.Book" scope="singleton" lazy-init="true"></bean>
  • 多例
<bean id="book" class="com.qfedu.ioc.bean.Book" scope="prototype"></bean>

2.6 Bean的聲明周期方法

在bean標簽中通過init-method屬性指定當前bean的初始化方法,初始化方法在構造器執行之后執行,通過destroy-method屬性指定當前bean的銷毀方法,銷毀方法在對象銷毀之前執行–>

  • Bean類

    public class Book {private int bookId;private String bookName;//初始化方法:在創建當前類對象時調用的方法,進行一些資源準備工作public void init(){System.out.println("-------init");}//銷毀方法:在Spring容器銷毀對象時調用此方法,進行一些資源回收性的操作public void destory(){System.out.println("-------destory");}
    }
    
  • Spring配置文件

    <bean id="book" class="com.qfedu.ioc.bean.Book" scope="prototype"init-method="init" destroy-method="destory" ></bean>
    

2.7 自動裝配

自動裝配:Spring在實例化當前bean的時候從Spring容器中找到匹配的實例賦值給當前bean的屬性

自動裝配策略有兩種:

  • byName 根據當前Bean的屬性名在Spring容器中尋找匹配的對象 ,如果根據name找打了bean但是類型不匹配則拋出異常
  • byType 根據當前Bean的屬性類型在Spring容器中尋找匹配的對象,如果根據類型找到了多個bean也會拋出異常
  • byName
<bean id="clazz" class="com.qfedu.ioc.bean.Clazz"></bean><bean id="stu2" class="com.qfedu.ioc.bean.Student" autowire="byName"></bean>
  • byType
<bean id="clazz2" class="com.qfedu.ioc.bean.Clazz"></bean><bean id="stu2" class="com.qfedu.ioc.bean.Student" autowire="byType"></bean>

2.8 SpringIoC 工作原理

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yZn6Wjb7-1639493961431)(imgs/1616752252731.png)]

三、Spring IoC — 基于注解

SpringIoc的使用,需要我們通過XML將類聲明給Spring容器進行管理,從而通過Spring工廠完成對象的創建及屬性值的注入;

Spring除了提供基于XML的配置方式,同時提供了基于注解的配置:直接在實體類中添加注解聲明給Spring容器管理,以簡化開發步驟。

3.1 Spring框架部署

3.1.1 創建Maven項目

3.2.2 添加SpringIoC依賴
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.13.RELEASE</version>
</dependency>
3.2.3 創建Spring配置文件
  • 因為Spring容器初始化時,只會加載applicationContext.xml文件,那么我們在實體類中添加的注解就不會被Spring掃描,所以我們需要在applicationContext.xml聲明Spring的掃描范圍,以達到Spring初始化時掃描帶有注解的實體類并完成初始化工作
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 聲明使用注解配置 --><context:annotation-config/><!-- 聲明Spring工廠注解的掃描范圍 --><context:component-scan base-package="com.qfedu.beans"/></beans>

3.2 IoC常用注解

3.2.1 @Component
  • 類注解,聲明此類被Spring容器進行管理,相當于bean標簽的作用
  • @Component(value="stu") value屬性用于指定當前bean的id,相當于bean標簽的id屬性;value屬性也可以省略,如果省略當前類的id默認為類名首字母改小寫
  • 除了@Component之外 @Service、@Controller、@Repository這三個注解也可以將類聲明給Spring管理,他們主要是語義上的區別
    • @Controller 注解主要聲明將控制器類配置給Spring管理,例如Servlet
    • @Service 注解主要聲明業務處理類配置Spring管理,Service接口的實現類
    • @Repository 直接主要聲明持久化類配置給Spring管理,DAO接口
    • @Component 除了控制器、servcie和DAO之外的類一律使用此注解聲明
3.2.2 @Scope
  • 類注解,用于聲明當前類單例模式還是 非單例模式,相當于bean標簽的scope屬性
  • @Scope(“prototype”) 表示聲明當前類為非單例模式(默認單例模式)
3.2.3 @Lazy
  • 類注解,用于聲明一個單例模式的Bean是否為懶漢模式
  • @Lazy(true) 表示聲明為懶漢模式,默認為餓漢模式
3.2.4 @PostConstruct
  • 方法注解,聲明一個方法為當前類的初始化方法(在構造器之后執行),相當于bean標簽的init-method屬性
3.2.5 @PreDestroy
  • 方法注解,聲明一個方法為當前類的銷毀方法(在對象從容器中釋放之前執行),相當于bean標簽的destory-method屬性
3.2.6 @Autowired
  • 屬性注解、方法注解(set方法),聲明當前屬性自動裝配,默認byType

  • @Autowired(required = false) 通過requried屬性設置當前自動裝配是否為必須(默認必須——如果沒有找到類型與屬性類型匹配的bean則拋出異常)

  • byType

  • ref引用

@Autowired
public void setClazz(@Qualifier("c2") Clazz clazz) {this.clazz = clazz;
}
3.2.7 @Resource
  • 屬性注解,也用于聲明屬性自動裝配
  • 默認裝配方式為byName,如果根據byName沒有找到對應的bean,則繼續根據byType尋找對應的bean,根據byType如果依然沒有找到Bean或者找到不止一個類型匹配的bean,則拋出異常。

四、代理設計模式

4.1 生活中的代理

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-C27d9xSd-1639493961434)(imgs/1616999162162.png)]

代理設計模式的優點:將通用性的工作都交給代理對象完成,被代理對象只需專注自己的核心業務。

4.2 靜態代理

靜態代理,代理類只能夠為特定的類生產代理對象,不能代理任意類

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-TFGLMB8C-1639493961434)(imgs/1617001027208.png)]

使用代理的好處

1.被代理類中只用關注核心業務的實現,將通用的管理型邏輯(事務管理、日志管理)和業務邏輯分離

2.將通用的代碼放在代理類中實現,提供了代碼的復用性

3.通過在代理類添加業務邏輯,實現對原有業務邏輯的擴展(增強)

4.3 動態代理

動態代理,幾乎可以為所有的類產生代理對象

動態代理的實現方式有2種:

  • JDK動態代理
  • CGLib動態大力
4.3.1 JDK動態代理
  • JDK動態代理類實現:
/**** JDK動態代理:是通過被代理對象實現的接口產生其代理對象的* 1.創建一個類,實現InvocationHandler接口,重寫invoke方法* 2.在類種定義一個Object類型的變量,并提供這個變量的有參構造器,用于將被代理對象傳遞進來* 3.定義getProxy方法,用于創建并返回代理對象*/
public class JDKDynamicProxy implements InvocationHandler {//被代理對象private Object obj;public JDKDynamicProxy(Object obj) {this.obj = obj;}//產生代理對象,返回代理對象public Object getProxy(){//1.獲取被代理對象的類加載器ClassLoader classLoader = obj.getClass().getClassLoader();//2.獲取被代理對象的類實現的接口Class<?>[] interfaces = obj.getClass().getInterfaces();//3.產生代理對象(通過被代理對象的類加載器及實現的接口)//第一個參數:被代理對象的類加載器//第二個參數:被代理對象實現的接口//第三個參數:使用產生代理對象調用方法時,用于攔截方法執行的處理器Object proxy = Proxy.newProxyInstance(classLoader, interfaces,this);return proxy;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {begin();Object returnValue = method.invoke(obj,args);  //執行method方法(insert)commit();return returnValue;}public void begin(){System.out.println("----------開啟事務");}public void commit(){System.out.println("----------提交事務");}
}
  • 測試
 //創建被代理對象
BookDAOImpl bookDAO = new BookDAOImpl();
StudentDAOImpl studentDAO = new StudentDAOImpl();//創建動態代理類對象,并將被代理對象傳遞到代理類中賦值給obj
JDKDynamicProxy jdkDynamicProxy = new JDKDynamicProxy(studentDAO);//proxy就是產生的代理對象:產生的代理對象可以強轉成被代理對象實現的接口類型
GenaralDAO proxy = (GenaralDAO)jdkDynamicProxy.getProxy();//使用代理對象調用方法,并不會執行調用的方法,而是進入到創建代理對象時指定的InvocationHandler類種的invoke方法
//調用的方法作為一個Method參數,傳遞給了invoke方法
proxy.insert(student);
4.3.2 CGLib動態代理

由于JDK動態代理是通過被代理類實現的接口來創建代理對象的,因此JDK動態代理只能代理實現了接口的類的對象。如果一個類沒有實現任何接口,該如何產生代理對象呢?

CGLib動態代理,是通過創建被代理類的子類來創建代理對象的,因此即使沒有實現任何接口的類也可以通過CGLib產生代理對象

CGLib動態代理不能為final類創建代理對象

  • 添加CGLib的依賴
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
  • CGLib動態代理實現:
/*** 1.添加cglib依賴* 2.創建一個類,實現MethodInterceptor接口,同時實現接口中的intercept方法* 3.在類中定義一個Object類型的變量,并提供這個變量的有參構造器,用于傳遞被代理對象* 4.定義getProxy方法創建并返回代理對象(代理對象是通過創建被代理類的子類來創建的)*/
public class CGLibDynamicProxy implements MethodInterceptor {private Object obj;public CGLibDynamicProxy(Object obj) {this.obj = obj;}public Object getProxy(){Enhancer enhancer = new Enhancer();enhancer.setSuperclass(obj.getClass());enhancer.setCallback(this);Object proxy = enhancer.create();return proxy;}public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {begin();Object returnValue = method.invoke(obj,objects); //通過反射調用被代理類的方法commit();return returnValue;}public void begin(){System.out.println("----------開啟事務");}public void commit(){System.out.println("----------提交事務");}
}
  • 測試
//創建被代理對象
BookDAOImpl bookDAO = new BookDAOImpl();
StudentDAOImpl studentDAO = new StudentDAOImpl();//通過cglib動態代理類創建代理對象
CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(bookDAO);
//代理對象實際上是被代理對象子類,因此代理對象可直接強轉為被代理類類型
BookDAOImpl proxy = (BookDAOImpl) cgLibDynamicProxy.getProxy();//使用對象調用方法,實際上并沒有執行這個方法,而是執行了代理類中的intercept方法,將當前調用的方法以及方法中的參數傳遞到intercept方法
proxy.update();

五、Spring AOP

5.1 AOP 概念

Aspect Oriented Programming 面向切面編程,是一種利用“橫切”的技術(底層實現就是動態代理),對原有的業務邏輯進行攔截,并且可以在這個攔截的橫切面上添加特定的業務邏輯,對原有的業務進行增強。

基于動態代理實現在不改變原有業務的情況下對業務邏輯進行增強

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UQSLw03Y-1639493961435)(imgs/1617008695615.png)]

5.2 Spring AOP框架部署

5.2.1 創建Maven項目
5.2.2 添加依賴
  • context
  • aspects
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.13.RELEASE</version>
</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.13.RELEASE</version>
</dependency>
5.2.3 創建spring配置文件
  • 需要引入aop的命名空間
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"></beans>

5.3 AOP配置—基于XML

在DAO的方法添加開啟事務和提交事務的邏輯

5.3.1 創建一個類,定義要添加的業務邏輯
public class TxManager {public void begin(){System.out.println("-----------開啟事務");}public void commit(){System.out.println("-----------提交事務");}}
5.3.2 配置aop
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="bookDAO" class="com.qfedu.dao.BookDAOImpl"></bean><bean id="studentDAO" class="com.qfedu.dao.StudentDAOImpl"></bean><!----><bean id="txManager" class="com.qfedu.utils.TxManager"></bean><aop:config><!--聲明切入點--><aop:pointcut id="book_all" expression="execution(* com.qfedu.dao.*.*(..))"/><!--聲明txManager為切面類--><aop:aspect ref="txManager"><!--通知--><aop:before method="begin" pointcut-ref="book_all"/><aop:after method="commit" pointcut-ref="book_all"/></aop:aspect></aop:config></beans>

AOP開發步驟

1.創建切面類,在切面類定義切點方法

2.將切面類配置給Spring容器

3.聲明切入點

4.配置AOP的通知策略

5.4 切入點的聲明

5.4.1 各種切入點聲明方式
<!--使用aop:pointcut標簽聲明切入點:切入點可以是一個方法-->
<aop:pointcut id="book_insert" expression="execution(* com.qfedu.dao.BookDAOImpl.insert())"/><!--BookDAOImpl類中所有無參數無返回值的方法-->
<aop:pointcut id="book_pc1" expression="execution(void com.qfedu.dao.BookDAOImpl.*())"/><!--BookDAOImpl類中所有無返回值的方法-->
<aop:pointcut id="book_pc2" expression="execution(void com.qfedu.dao.BookDAOImpl.*(..))"/><!--BookDAOImpl類中所有無參數的方法-->
<aop:pointcut id="book_pc3" expression="execution(* com.qfedu.dao.BookDAOImpl.*())"/><!--BookDAOImpl類中所有方法-->
<aop:pointcut id="book_pc4" expression="execution(* com.qfedu.dao.BookDAOImpl.*(..))"/><!--dao包中所有類中的所有方法-->
<aop:pointcut id="pc5" expression="execution(* com.qfedu.dao.*.*(..))"/><!--dao包中所有類中的insert方法-->
<aop:pointcut id="pc6" expression="execution(* com.qfedu.dao.*.insert(..))"/><!--dao包中所有類中的insert方法-->
<aop:pointcut id="pc7" expression="execution(* *(..))"/>
5.4.2 AOP使用注意事項
//如果要使用Spring aop面向切面編程,調用切入點方法的對象必須通過Spring容器獲取
//如果一個類中的方法被聲明為切入點并且織入了切點之后,通過Spring容器獲取該類對象,實則獲取到的是一個代理對象
//如果一個類中的方法沒有被聲明為切入點,通過Spring容器獲取的就是這個類真實創建的對象
//BookServiceImpl bookService = new BookServiceImpl();
BookServiceImpl bookService = (BookServiceImpl) context.getBean("bookServiceImpl");
bookService.addBook();

5.5 AOP通知策略

AOP通知策略:就是聲明將切面類中的切點方法如何織入到切入點

  • before
  • after
  • after-throwing
  • after-returning
  • around
5.5.1 定義切面類
public class MyAspect {public void method1(){System.out.println("~~~~~~~method1");}public void method2(){System.out.println("~~~~~~~method2");}public void method3(){System.out.println("~~~~~~~method3");}public void method4(){System.out.println("~~~~~~~method4");}//環繞通知的切點方法,必須準守如下的定義規則://1.必須帶有一個ProceedingJoinPoint類型的參數//2.必須有Object類型的返回值//3.在前后增強的業務邏輯之間執行Object v = point.proceed();//4.方法最后返回vpublic Object method5(ProceedingJoinPoint point) throws Throwable {System.out.println("~~~~~~~method5---before");//此代碼的執行,就表示切入點方法的執行Object v = point.proceed();System.out.println("~~~~~~~method5---after");return v;}}
5.5.2 配置切面類
<bean id="myAspect" class="com.qfedu.utils.MyAspect"></bean>
<aop:config><!--使用aop:pointcut標簽聲明切入點:切入點可以是一個方法--><aop:pointcut id="book_insert" expression="execution(* com.qfedu.dao.BookDAOImpl.insert())"/><aop:aspect ref="myAspect"><!--aop:before 前置通知,切入到指定切入點之前--><aop:before method="method1" pointcut-ref="book_insert"/><!--aop:after 后置通知,切入到指定切入點之后--><aop:after method="method2" pointcut-ref="book_insert"/><!--aop:after-throwing 異常通知,切入點拋出異常之后--><aop:after-throwing method="method3" pointcut-ref="book_insert"/><!--aop:after-returning 方法返回值返回之后,對于一個Java方法而言return返回值也是方法的一部分因此“方法返回值返回之后”和“方法執行結束”是同一個時間點,隨意after 和 after-returning根據配置的順序決定執行順序--><aop:after-returning method="method4" pointcut-ref="book_insert"/><aop:around method="method5" pointcut-ref="book_insert"/></aop:aspect></aop:config>

六、Spring AOP 注解配置

6.1 Spring AOP 注解配置框架部署

6.1.1 創建Maven工程
6.1.2 添加Spring依賴
  • context
  • aspects
6.1.3 Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><context:annotation-config></context:annotation-config><context:component-scan base-package="com.qfedu"></context:component-scan><!--  基于注解配置的aop代理  --><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>

6.2 AOP注解配置案例

@Component
@Aspect
public class TransactionManager {@Pointcut("execution(* com.qfedu.dao.*.*(..))")public void pc1(){}@Before("pc1()")public void begin(){System.out.println("~~~~開啟事務");}@After("pc1()")public void commit(){System.out.println("~~~~提交事務");}@Around("pc1()")public Object printExecuteTime(ProceedingJoinPoint point) throws Throwable {long time1 = System.currentTimeMillis();Object v = point.proceed();long time2 = System.currentTimeMillis();System.out.println("----time:"+(time2-time1));return v;}}

注意:注解使用雖然方便,但是只能在源碼上添加注解,因此我們的自定義類提倡使用注解配置;但如果如果使用到第三方提供的類則需要通過xml配置形式完成配置。

七、Spring整合MyBatis

Spring兩大核心思想:IoC 和 AOP

IoC : 控制反轉,Spring容器可以完成對象的創建、屬性注入、對象管理等工作

AOP : 面向切面,在不修改原有業務邏輯的情況下,實現原有業務的增強

7.1 Spring可以對MyBatis提供哪些支持?

  • IoC支持 SpringIoC 可以為MyBatis完成DataSource、SqlSessionFactory、SqlSession以及DAO對象的創建

  • AOP支持使用Spring提供的事務管理切面類完成對MyBatis數據庫操作中的事務管理

7.2 Spring整合MyBatis準備工作

7.2.1 創建Maven工程
7.2.2 部署MyBatis框架
  • 添加依賴
    • Mysql驅動
    • mybatis
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version>
</dependency><!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version>
</dependency>
  • 創建MyBatis配置文件(創建配置文件之后無需進行任何配置)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration></configuration>
7.2.3 部署Spring框架
  • 添加依賴
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.13.RELEASE</version>
</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.13.RELEASE</version>
</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.13.RELEASE</version>
</dependency>
  • 創建Spring配置文件:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"></beans>
7.2.4 添加Spring整合MyBatis的依賴
  • mybatis-spring 就是mybatis提供的兼容Spring的補丁
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.2</version>
</dependency>

7.3 Spring整合MyBatis整合IoC配置

7.3.1 整合Druid連接池
  • 添加druid的依賴
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version>
</dependency>
  • 創建druid.properties屬性文件
druid.driver=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/db_2010_mybatis?characterEncoding=utf-8
druid.username=root
druid.password=admin123## 連接池參數
druid.pool.init=1
druid.pool.minIdle=3
druid.pool.maxActive=20
druid.pool.timeout=30000
  • 在applicationContext.xml中配置DruidDataSource
<!--加載druid.properties屬性文件-->
<context:property-placeholder location="classpath:druid.properties"/><!--依賴Spring容器完成數據源DataSource的創建-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${druid.driver}"/><property name="url" value="${druid.url}"/><property name="username" value="${druid.username}"/><property name="password" value="${druid.password}"/><property name="initialSize" value="${druid.pool.init}"/><property name="minIdle" value="${druid.pool.minIdle}"/><property name="maxActive" value="${druid.pool.maxActive}"/><property name="maxWait" value="${druid.pool.timeout}"/>
</bean>
7.3.2 整合MyBatis—創建SqlSessionFactory

依賴Spring容器創建MyBatis的SqlSessionFactory對象

<!--依賴Spring容器完成MyBatis的SqlSessionFactory對象的創建-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" ><!--配置數據源--><property name="dataSource" ref="druidDataSource"/><!--配置mapper文件的路徑--><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/><!--配置需要定義別名的實體類的包--><property name="typeAliasesPackage" value="com.qfedu.pojo"/><!--可選:配置MyBatis的主配置文件--><property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
7.3.3 整合MyBatis-創建Mapper
<!--加載dao包中的所有DAO接口,通過sqlSessionFactory獲取SqlSession,然后創建所有的DAO接口對象,存儲在Spring容器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><property name="basePackage" value="com.qfedu.dao"/>
</bean>

7.4 Spring整合MyBatis整合AOP配置

使用Spring提供的事務管理切面類 完成DAO中增刪改操作的事務管理

7.4.1 事務的隔離級別

isolation 設置事務隔離級別:READ_UNCOMMITTED ,READ_COMMITTED , REPEATABLE_READ , SERIALIZABLE

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2n7fkSq9-1639493961436)(imgs/1617093621853.png)]

7.4.2 事務的傳播機制

propagation 設置事務的傳播機制

  • REQUIRED 如果上層方法沒有事務,則創建一個新的事務;如果已經存在事務,則加入到事務中。

  • SUPPORTS 如果上層方法沒有事務,則以非事務方式執行;如果已經存在事務,則加入到事務中。

  • REQUIRES_NEW 如果上層方法沒有事務,則創建一個新的事務;如果已經存在事務,則將當前事務掛起。

  • NOT_SUPPORTED 如果上層方法沒有事務,則以非事務方式執行;如果已經存在事務,則將當前事務掛起。

  • NEVER 如果上層方法沒有事務,則以非事務方式執行;如果已經存在事務,則拋出異常。

  • MANDATORY 如果上層方法已經存在事務,則加入到事務中執行;如果不存在事務則拋出異常。

  • NESTED 如果上層方法沒有事務,則創建一個新的事務;如果已經存在事務,則嵌套到當前事務中。

7.4.3 Spring AOP事務管理配置—XML配置
<!--1.將Spring提供的事務管理配置配置給Spring容器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="druidDataSource"/>
</bean><!--2.通過Spring jdbc提供的 tx標簽,聲明事務管理策略-->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/><tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED"/><tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED"/><tx:method name="query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/></tx:attributes>
</tx:advice><!--3.將事務管理策略以AOP配置 應用于DAO操作方法-->
<aop:config><aop:pointcut id="crud" expression="execution(* com.qfedu.service.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="crud"/>
</aop:config>
7.4.4 Spring AOP事務管理配置—注解配置
  • 在applicationContext.xml中配置事務管理,聲明使用注解方式進行事務配置
<!--使用注解進行事務管理前提是 IoC需要進行注解配置-->
<context:annotation-config/>
<context:component-scan base-package="com.qfedu"/><!--1.將Spring提供的事務管理配置配置給Spring容器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="druidDataSource"/>
</bean><!--2.聲明使用注解完成事務配置-->
<tx:annotation-driven transaction-manager="transactionManager"/>
  • 在需要Spring進行事務管理的方法上添加@Transactional注解
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.SUPPORTS )
public List<User> listUsers() {return userDAO.queryUsers();
}

八、基于Spring的單元測試

如果想要使用Spring容器實現屬性注入、實現AOP面向切面編程,對象必須通過Spring容器獲取;為了便于Spring環境下的測試,Spring提供了test組件,專門針對Spring環境進行單元測試。

8.1 添加依賴

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.13.RELEASE</version>
</dependency>

8.2 編寫單元測試類

8.2.1 創建一個單元測試類

8.2.2 添加注解
//1.通過@RunWith 聲明當前測試類位于Spring容器環境(被Spring容器管理)
@RunWith(SpringJUnit4ClassRunner.class)
//2.通過@ContextConfiguration 聲明當前測試環境的Spring容器運行時加載的配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class UserServiceImplTest {//因為當前測試類是基于Spring容器運行的,當前測試類的對象是通過Spring容器創建的//因此可以通過Spring容器實現屬性的注入@Resourceprivate UserService userServiceImpl2;@Resourceprivate UserService userServiceImpl;@Testpublic void test(){List<User> users = userServiceImpl.listUsers();System.out.println(users);}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450428.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450428.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450428.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux系統下的權限試題測試

不會做的留言&#xff0c;到時在發布答案&#xff01;一、 有兩個參賽團隊team1、team2&#xff0c;兩個團隊各3人, 這兩個團隊互相競爭&#xff0c;各需提交一份報告&#xff0c;每組成員可以修改自己團隊內的所有文件&#xff0c;且不能讓其他團隊的人修改自己的文件內容&…

電子科大軟件系統架構設計——軟件建模詳細設計

文章目錄 軟件建模詳細設計概述軟件建模詳細設計目標軟件建模詳細設計原則開閉原則里氏 (Liskov) 替換原則依賴倒置原則接口分離原則單一職責原則最少知識原則&#xff08;迪米特法則&#xff09;高內聚原則松耦合原則可重用原則 軟件建模詳細設計內容 UML 軟件靜態結構視圖建模…

YAML文件解析

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 YAML是“另一種標記語言”的外語縮寫,YAML 是一種比JSON&#xff08;json多層次{ 與 [ 會被搞暈的&#xff09;更直觀的表現形式&#xf…

120分鐘React快速掃盲教程

在教程開端先說些題外話&#xff0c;我喜歡在學習一門新技術或讀過一本書后&#xff0c;寫一篇教程或總結&#xff0c;既能幫助消化&#xff0c;也能加深印象和發現自己未注意的細節&#xff0c;寫的過程其實仍然是一個學習的過程。有個記錄的話&#xff0c;在未來需要用到相關…

springmvc知識點

一、SpringMVC概述 Spring MVC 是由Spring官方提供的基于MVC設計理念的web框架。 SpringMVC是基于Servlet封裝的用于實現MVC控制的框架&#xff0c;實現前端和服務端的交互。 1.1 SpringMVC優勢 嚴格遵守了MVC分層思想 采用了松耦合、插件式結構&#xff1b;相比較于我們封裝的…

spring @component的作用

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1、controller 控制器&#xff08;注入服務&#xff09; 2、service 服務&#xff08;注入dao&#xff09; 3、repository dao&#xff…

微信小程序 懸浮按鈕

2019獨角獸企業重金招聘Python工程師標準>>> 效果視頻 https://pan.baidu.com/s/1yfrDaG9YAX0--v0EA3awZA 布局需要按照圓形排列&#xff0c;所以我們需要計算每個點的坐標 代碼部分 <view styleposition:fixed; wx:for"{{list}}" wx:for-index"i…

C語言const關鍵字—也許該被替換為readolny

const 是constant 的縮寫&#xff0c;是恒定不變的意思&#xff0c;也翻譯為常量、常數等。很不幸&#xff0c;正是因為這一點&#xff0c;很多人都認為被const 修飾的值是常量。這是不精確的&#xff0c;精確的說應該是只讀的變量&#xff0c;其值在編譯時不能被使用&#xff…

dbus服務自啟動方法

Linux 一般發行版上 "/usr/share/dbus-1/services/"目錄就是dbus放service文件的地方。 需要自動啟動的服務器 就在這個目錄放一個 service文件&#xff0c;內容如下&#xff1a; $ cat /usr/share/dbus-1/services/dhcdbd.service [D-BUS Service] Namecom.redhat.…

在Spring Boot中使用 @ConfigurationProperties 注解

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 上一篇博客寫了 如何在Spring Boot application中配置mail . 使用 Value 注解注入屬性. 但 Spring Boot 提供了另一種方式 &#xff0c;能…

Micronaut教程:如何使用基于JVM的框架構建微服務

\本文要點\\Micronaut是一種基于jvm的現代化全棧框架&#xff0c;用于構建模塊化且易于測試的微服務應用程序。\\tMicronaut提供完全的編譯時、反射無關的依賴注入和AOP。\\t該框架的開發團隊和Grails框架的開發團隊是同一個。\\tMicronaut框架集成了云技術&#xff0c;服務發現…

C語言extern關鍵詞—最會帶帽子的關鍵字

extern&#xff0c;外面的、外來的意思。那它有什么作用呢&#xff1f;舉個例子&#xff1a;假設你在大街上看到一個黑皮膚綠眼睛紅頭發的美女&#xff08;外星人&#xff1f;&#xff09;或者帥哥。你的第一反應就是這人不是國產的。extern 就相當于他們的這些區別于中國人的特…

解決Coldfusion連接MySQL數據庫的問題

在連接MySQL時&#xff0c;出現了如下錯誤&#xff1a; Connections to MySQL Community Server are not supported. Please contact MySQL to obtain a MySQL Enterprise or Commercial version. 解決方案&#xff1a; step 1: download the JDBC driver JDBC Driver for MySQ…

范式知識點

Mysql數據庫 ?前關系數據庫有六種范式&#xff1a; 第?范式&#xff08;1NF&#xff09;、第?范式&#xff08;2NF&#xff09;、第三范式&#xff08;3NF&#xff09;、巴斯-科德范式 &#xff08;BCNF&#xff09;、第四范式(4NF&#xff09;和第五范式&#xff08;5NF&a…

Tensorflow入門----占位符、常量和Session

安裝好TensorFlow之后&#xff0c;開一個python環境&#xff0c;就可以開始運行和使用TensorFlow了。 先給一個實例&#xff0c; #先導入TensorFlowimport tensorflow as tf # Create TensorFlow object called hello_constanthello_constant tf.constant(Hello World!) with …

C語言union關鍵字

union 關鍵字的用法與struct 的用法非常類似。union 維護足夠的空間來置放多個數據成員中的“一種”&#xff0c;而不是為每一個數據成員配置空間&#xff0c;在union 中所有的數據成員共用一個空間&#xff0c;同一時間只能儲存其中一個數據成員&#xff0c;所有的數據成員具有…

js 深拷貝 和 淺拷貝

1、 ...運算符 &#xff08;淺拷貝&#xff09; let obj {a:1,b:2}; let obj2 {...obj}; obj.a3 obj //{a: 3, b: 2} obj2 //{a: 1, b: 2}a {a:[{b:1}]}; b a ;b.a[0].b 2; //b {a:[{b:2}]}a // a {a:[{b:2}]} 2、 JSON.parse(JSON.stringify(參數))…

軟考如何備考

軟考上半年 報名時間 3月 考試時間 5月 備考持續時間&#xff1a;一個半月&#xff0c;每天至少兩個小時。 第一輪 基礎知識輪&#xff0c; 15天 在這一輪中如果碰到無法理解的知識點一定不要過于糾結&#xff0c;往后學&#xff0c;一般后面的學著學著之前的內容就…

Python學習第一天-第2節

*本節課內容參見&#xff1a;https://www.cnblogs.com/jin-xin/articles/7459977.html運行第一個Python程序 print(hello world) 將文本文件保存為以.py結尾的文件&#xff0c;如hello_world.py &#xff0c;在終端中&#xff0c;運行命令&#xff1a;Python hello_world.py&am…

SpringMVC之組合注解@GetMapping

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Spring4.3中引進了&#xff5b;GetMapping、PostMapping、PutMapping、DeleteMapping、PatchMapping&#xff5d;&#xff0c;來幫助簡化…