日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring知识概要

發(fā)布時間:2025/3/20 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring知识概要 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

文章目錄

  • **Spring基礎(chǔ)**
  • **Spring容器**
  • **Spring創(chuàng)建Bean的3種方式**
  • **Spring容器中Bean的作用域**
  • **Spring核心機(jī)制:依賴注入**
      • **1.注入方式**
      • **2 各種注入示例**
  • **Spring的組合屬性**
  • **Spring的Java配置管理**
  • **深入理解Spring容器中的Bean**
      • 1. 抽象Bean
      • 2. 繼承Bean
      • 3 .Spring中Bean的繼承與Java中類的繼承的區(qū)別:
      • 4.工廠Bean
  • **Spring中Bean的生命周期**
  • **Spring的其他依賴配置**
      • 1. 使用PropertyPathFactoryBean獲取其他Bean的屬性值
      • 2. 使用FieldRetrivingFactoryBean獲取其他Bean的Field值
      • 3. 使用MethodInvokingFactoryBean獲取其他Bean的方法的返回值
  • **Spring基于xml Schema的簡化配置**
      • 1. p:命名空間
      • 2. c:命名空間
      • 3. util命名空間
      • 4.Spring的其他簡化配置的schema
  • **spring的兩種后處理器**
      • 1. Bean后處理器
      • 2. 容器后處理器
      • 3.容器后處理器之屬性占位符配置器
      • 4.容器后處理器之重寫占位符配置器
  • **Spring 注解之零配置**
      • 1.指定SpringBean的注解
      • 2.搜索Spring Bean
      • 3.配置依賴的@Resource注解
      • 4.指定Bean作用域的@Scope注解
      • 5 定制SpringBean生命周期行為的注解
      • 6 自動裝配和精裝配的注解
      • 7 Spring的其他注解
  • **Spring的AOP**
    • **1 基于注解管理的AOP**
    • **2基于xml配置的AOP**
  • **Spring的事務(wù)**
    • 1. Spring支持的事務(wù)策略
      • 1.1 全局事務(wù)
      • 1.3 PlatformTransactionManager
    • 2 Spring的兩種事務(wù)管理方式
    • 3 spring事務(wù)的傳播屬性
  • Spring補(bǔ)充知識
    • ApplicationContextAware
    • 注解@ControllerAdvice

Spring基礎(chǔ)

  • 基本上所有的框架都是提取實際開發(fā)中大量重復(fù)步驟而成
  • 圍繞Spring框架,還衍生出了如Spring Web Flow、Spring Security等框架
  • Spring框架優(yōu)點
    1) 低侵入式,代碼污染低
    2) 獨立于各種應(yīng)用服務(wù)器
    3) IOC降低了業(yè)務(wù)對象替換的復(fù)雜性,降低了組件之間的耦合
    4) AOP支持通用任務(wù)如日志、事務(wù)、安全等的集中處理
    5) ORM和DAO提供了與第三方持久框架的良好整合,并簡化了底層數(shù)據(jù)庫的訪問
    6) 開發(fā)者可自由選擇Spring框架的部分或全部,不像有些框架得全部引用
  • Spring容器(Spring Core Container)是Spring的核心機(jī)制,它主要由以下4個包和其子包組成:
    a) org.springframework.core
    b) org.springframework.beans
    c) org.springframework.content
    d) org.springframework.expression
    spring容器還依賴于common-logging 這個JAR包
  • Spring容器中的Bean是一個泛化概念,只要是一個Java類就可當(dāng)成Bean。Spring容器使用xml配置文件來管理這些Bean,所以配置到XML文件中的Bean,Spring容器就可管理它。
  • 一個對象需要調(diào)用另一個對象的情形就可稱為依賴
  • Spring容器利用XML配置文件管理Bean的原理
    我們將Bean配置在XML文件里后,在創(chuàng)建Spring容器后,Spring容器就開始解析Xml文件。當(dāng)解析到<bean…/>元素里class屬性的完整類名時,就會利用反射機(jī)制實例化一個對象,當(dāng)解析到<property…/>元素時,就會執(zhí)行該對象的setter方法,其中name屬性決定執(zhí)行哪個setter方法,value或ref屬性決定setter方法的傳入?yún)?shù)。最后在完成注入后,將<bean…/>元素里的id屬性值和創(chuàng)建的對象以鍵值對的形式存在Spring容器中,這樣Spring容器就可管理Bean了。
  • XML配置文件中<property…/>元素什么時候用value屬性,什么時候用ref屬性?
    a) 當(dāng)傳入?yún)?shù)是基本數(shù)據(jù)類型或String類型時用vlaue
    b) 當(dāng)傳入?yún)?shù)是其他Bean時,則用ref(即引用類型用ref)
  • 如何訪問Spring容器中的Bean?
    常用ApplicationContext接口的實現(xiàn)類來獲取,該接口主要有以下兩個方法:
    a) Object getBean(String name):獲取容器中id為name的Bean實例
    b) T getBean(String id,Class<T> type):根據(jù)id名和Bean類型獲取該Bean
    ApplicationContext接口的主要實現(xiàn)類:
    a) ClassPathXmlApplicationContext :從類加載路徑下搜索配置文件
    b) FileSystemXmlApplicationContext:從文件系統(tǒng)的相對或絕對路徑下搜索配置文件
    c) AnnotationConfigWebApplicationContext:使用注解替換xml配置文件時使用【單測時用比較方便】
    示例:
  • ApplicationContext app = new ClassPathXmlApplicationContext(“beans.xml”); User user = (User) app.getBean(“user”)

    10.總結(jié)
    有了spring后,程序可不再使用new來創(chuàng)建對象了

    Spring容器

  • 由前面了解到,Spring容器是利用xml配置文件來生產(chǎn)并管理Bean的,而訪問Spring容器中的Bean利用了Application接口,所以我們用該接口來代表Spring容器。實際上,ApplicationContext的父接口BeanFactroy也可代表Spring容器,但我們一般不用它作為Spring容器,除非應(yīng)用對內(nèi)存非常關(guān)鍵。
  • ApplicationContext容器接口 除有BeanFactory全部功能以外,還有以下功能:
    a) 在創(chuàng)建容器時就初始化容器中的Bean,可通過<bean…/>元素的lazy-init=”true”取消
    b) 因繼承了MessageSource接口所以支持國際化
    c) 支持資源訪問,如URL和文件
    d) 支持事件機(jī)制
    e) 可同時加載多個配置文件
    f) 能通過聲明方式啟動并創(chuàng)建Spring容器
  • ApplicationContext接口的實現(xiàn)類
    a) 常用實現(xiàn)類:
    ClassPathXmlApplicationContext:從類加載路徑下搜索配置文件
    FileSystemXmlApplicationContext:從文件系統(tǒng)的相對或絕對路徑下搜索配置文件
    AnnotationConfigApplicationContext:使用Java配置替換xml配置文件時使用
    b) 在web應(yīng)用中常用的實現(xiàn)類:
    XmlWebApplicationContext:
    AnnotationConfigWebApplicationContext:使用注解替換xml配置文件時使用
  • 編程式實例化ApplicationContext
    ApplicationContext app = new ClassPathXmlApplicationContext(“beans.xml”);
  • 聲時式創(chuàng)建并啟動Spring容器(ApplicationContext)
  • 當(dāng)beans.xml文件放在WEB-INF下時,只需在web.xml中配置:
  • <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
  • 當(dāng)beans.xml放在src目錄(即classpath)下時,則需在web.xml當(dāng)中配置:
  • <context-param><!-- 加載spring容器:單詞不能寫錯 --><param-name>contextConfigLocation</param-name><param-value>classpath: beans.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>

    當(dāng)有多個配置文件時,可在classpath后面使用通配符“*”

    Spring創(chuàng)建Bean的3種方式

  • Spring創(chuàng)建Bean的3種方式
    a) 調(diào)用構(gòu)造器
    b) 調(diào)用靜態(tài)工廠方法
    c) 調(diào)用實例工廠方法
  • 使用靜態(tài)工廠方法
  • 此時<bean…/>元素需要指定以下兩屬性
    a) class:指定靜態(tài)工廠類的類名
    b) factory-method:指定創(chuàng)建實例的靜態(tài)工廠方法
  • 示例
  • public class Dog implements Animal{ //要求類化的類private String msg;public void setMsg(String msg){this.msg = msg;}public void eat(){System.out.print(msg);} } public class Dog AnimalFactory{ //靜態(tài)工廠類代碼public static Animal getAnimal(String name){if(“dog”.equalsIgnoreCase(name)){return new Dog();}else{return new Cat();}} } //對應(yīng)配置文件 <bean id="dog" class="com.dfsj.AnimalFactory" factory-method=”getAnimal”><constructor-arg value="dog"/><property name="msg" value="我是狗"/>></bean>

    需要注意的是,靜態(tài)工廠方法的參數(shù)通過<constructor-arg…/>元素配置,而新建對象的屬性的值通過<property…/>元素設(shè)置

    3.使用實例工廠方法創(chuàng)建Bean時,<bean…/>元素需要指定如下兩屬性:
    a) factory-bean:指定工廠類實例,即工廠類在配置文件中的id
    b) factory-method:指定實例工廠創(chuàng)建實例方法

    4.靜態(tài)工廠方法與實例工廠方法的區(qū)別:
    不同點:
    a) 靜態(tài)工故事有class屬性,指定的是靜態(tài) 工廠類的類名,而實例工廠是用factory-bean屬性指定工廠類在配置文件中的id
    b) 靜態(tài)工廠方法創(chuàng)建Bean實例的方法是靜態(tài)的
    相同點
    a) 都需要用factory-method指定創(chuàng)建Bean實例的方法
    b) 工廠方法里的參數(shù)都必須通過<constructor-arg…/>元素來配置
    c) 給新創(chuàng)建的Bean實例的屬性賦值,都是用<property…/>元素

    Spring容器中Bean的作用域

    1. Spring容器的bean的作用域通過sope屬性指定

    <bean id=”test” class=”com.dfsj.Test” scope=”prototype”>
  • 常用的兩個作用域
    a) singleton:在IOC容器中只生成一個實例
    b) prototype:每次通過容器的getBean()方法獲取該作用域的Bean時,都將產(chǎn)生一個新的實例
  • 只在web項目中有效的幾個作用域
    a) reqeust:對于一次http請求,該作用域下的Bean只生成一個實例
    b) session:對于一次會話,只生成一個實例
    c) global session:在全局會話,里生成一個實例
  • 在web.xml中配置使request作用域生效的Listener
  • <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>

    5 注
    在springMVC框架中,已有SpringDispatherServlet或DispatherServlet來攔截處理所有和請求有關(guān)的狀態(tài)處理,所以不需要如編號4的Listerner配置。

    6. 這里的bean的作用域具體指的是什么?
    如果一個bean的scope屬性設(shè)置為singleton,則表示在整個IOC容器內(nèi),在注入到其他對象中時,只要唯一確定是該bean(可通過id確定),則都會是同一個bean,而不是去重新new一個新的bean對象。
    如果一個bean的scope屬性設(shè)置為prototype,則表示在注入到其他對象中或用getBean方法得到時,雖然指向的是同一個bean,但都會重新new一個新的對象。

    Spring核心機(jī)制:依賴注入

    1.注入方式

  • 設(shè)值注入
  • <bean id=”user” class=”com.app.User”><property name=”name” vlaue=”張三”/><property name=”age” vlaue=”30”/> </bean>

    2.構(gòu)造注入

    <bean id="test" class="com.test.Test"><property name="name" value="Peter"/> <constructor-arg ref="person"/><constructor-arg value="張三" type="String"/> </bean> 構(gòu)造注入的參數(shù)序安出現(xiàn)的順序為準(zhǔn),除非以index屬性指定(下標(biāo)從0開始)

    3.在使用spring框架時,眼睛看到xml配置時,心中要想到底層Java代碼是如何實現(xiàn)的,用得熟練時,看到任何一段Java代碼都能用xml文件配置也來

    2 各種注入示例

  • 以參數(shù)下標(biāo)方式配置有參構(gòu)造,不指定index時,以出現(xiàn)順序注入
  • <bean id="test" class="com.test.Test">< constructor-arg index=”0” value="ddd"/> <constructor-arg index=”1” value=”44”/> </bean>

    2.注入基本數(shù)據(jù)類型

    <bean id="test" class="com.test.Test">< property name=”name” value="ddd"/> < property name=”age” value="30"/> </bean>

    3.注入其他Bean

    <bean id="dog" class="com.test.Dog"> <bean id="test" class="com.test.Test">< property name=”dog” ref="dog"/> </bean>

    4.注入嵌套Bean

    <bean id="test" class="com.test.Test">< property name=”cat” > <bean class=”com.test.Cat”></property> </bean>

    5.注入Map集合
    entry元素有4個屬性:
    key:當(dāng)key值是基本數(shù)據(jù)類型或字符串類型時使用
    key-ref:當(dāng)key值是引用類型時使用
    value:當(dāng)value值是基本數(shù)據(jù)或字符串類型時使用
    value-ref:當(dāng)value值是引用類型時使用
    示例:給private Map<String,Axe> axes注入

    <bean id="test" class="com.test.Test">< property name=”axes” > <map><entry key=”name” value=”張三”/></map></property></bean>

    6.注入數(shù)組(與注入List集合一樣):如給private String[] cities;注入

    <bean id="test" class="com.test.Test">< property name=”cities” > <list>< value=”北京”/>< value=”重慶”/></list></property> </bean>

    7.注入List集合:如給private List<String> cities;注入

    <bean id="test" class="com.test.Test">< property name=”cities” > <list>< value=”北京”/>< value=”重慶”/></list></property> </bean>

    8.注入Properties集合(Properties類實現(xiàn)了Map接口)

    <bean id="test" class="com.test.Test">< property name=”health” > <props><prop key=”血壓” >正常</prop><prop key=”身高” >175</prop></props></property></bean>

    9.注入Set集合:如給private Set set注(因為泛型,所以可以注入各種類型的)

    <bean id="test" class="com.test.Test">< property name=”set” > <set>< value>普通字符串< value/> //基本數(shù)據(jù)類型或字符串<bean class=”com.test.User”> //嵌套Bean<ref brean=”stoneAxe”> //容器中的其他Bean<list> //List集合< value>20< value/><set>< value>30< value/></set></list></set></property> </bean>

    10.當(dāng)<list…/>、<set…/>、<map…/>這些元素在配置注入時,如果這些集合未泛型,則其值可以是基本數(shù)據(jù)類型、字符串、容器中其他Bean、嵌套Bean、集合等各種數(shù)據(jù)類型,如上面Set集合注入的示例

    Spring的組合屬性

    1. 所謂組合屬性,就是一個類的屬性還有自己的屬性。因為涉及到調(diào)用,所以在使用組合屬性時,除最后一個屬性外,前面調(diào)用者都不能為空。
    2. 示例

    Java代碼: public class Test{ private Person person = new Person; //這里一定要new//….getter 、setter方法 } 對應(yīng)配置代碼: <bean id="person" class="com.test.Person" /> <bean id="test" class="com.test.Test">< property name=”person.name” value=”張三” > </bean>

    3.Spring中的Bean與Java的Bean的區(qū)別

  • 寫法不同:
    傳統(tǒng)的JavaBean作為對象,要求每個屬性都必須提供getter setter方法,而SpringBean只需要為接受設(shè)值注入的屬性提供setter方法即可,但是如果要獲取該屬性值,還是需要寫getter方法的
  • 生命周期的不同:
    傳統(tǒng)的JavaBean不接受容器的管理,而SpringBean是由spring容器管理它的生命周期和行為的
  • Spring中的Bean即使有"有參構(gòu)造函數(shù),最好也提供無參構(gòu)造函數(shù)
  • Spring的Java配置管理

    Spring的Java配置管理,代替了之前的xml文件配置管理
    1. 實現(xiàn)
    1)利用**@Configuration注解修飾的類(后面就叫配置類)代替xml文件
    2)有
    @Bean**注解修飾一個方法,該方法的返回的對象將定義成容器中的Bean
    3)用@Value注解修飾一個Field,相當(dāng)于配置一個變量
    2. 示例

    @Configuration public class AppConfig{ @Value("張三") String personName;@Bean(name="chinese")public Person getPerson(){Chinese c = new Chinese();c.setAxe(getStoneAxe ()); // 獲取stoneAxe對象并注入c.setName(personName);return c;}@Bean(name="stoneAxe")public Axe getStoneAxe(){return new StoneAxe();} }

    3.Java配置管理時創(chuàng)建容器

    ApplicationContext app = new AnnotationConfigApplicationContext(AppConfig.class);

    如果是web應(yīng)用,則用AnnotationConfigWebApplicationContext創(chuàng)建
    4.XML配置管理與Java配置管理的混用
    1)在xml配置文件中導(dǎo)入Java配置類

    <bean class="com.dfsj.util.AppConfig">

    2)在Java配置類里導(dǎo)入xml配置文件

    @Configuration @ImportResource("classpath:/beans.xml") public class AppConfig{ //…. }

    5.Java配置類的其他注解
    1)@Import:修飾Java類,用于導(dǎo)入其他Java配置類
    2)@Scope:修飾創(chuàng)建Bean的方法,用于指定生成的Bean的作用域
    3)@Lazy:修飾創(chuàng)建Bean的方法,用于指定生成Bean是否延遲初始化
    4)@DependsOn:修飾創(chuàng)建Bean的方法,用于指定在初始該方法前要初始化的其他Bean

    深入理解Spring容器中的Bean

    1. 抽象Bean

    1)抽象Bean由<bean.../>元素的abstract="true"屬性指定,如:

    <bean id="test" abstract="true"><property name="username" value="peter"/><property name="age" value="peter"/> </bean>

    從上面示例中可以看到,并沒有用class屬性指定類,這是為什么呢?
    因為我們知道,抽象Bean是不可被實例化的,即便指了類的完整名也不會用到,還有就是,Spring中的Bean的繼承是對象與對象之間的關(guān)系,而不是類與類之間的關(guān)系,只存在參數(shù)之間的傳遞,所以抽象類須指定參數(shù)。抽象類的屬性值,在子類當(dāng)中也能獲取到。

    2. 繼承Bean

    1)在Spring中,Bean的繼承是由parent屬性指定的,如:

    <bean id="son" class="com.dfsj.Son" parent="test"> parent指定的值是父類在容器中的id

    2)當(dāng)子類信息與父類信息不一致時,子類的覆蓋父類的
    3)子類無法從父類繼承這些屬性:depends-on、autowire、singleton、scope、lazy-init

    3 .Spring中Bean的繼承與Java中類的繼承的區(qū)別:

    1)前者是對象與對象之間的關(guān)系,后者是類與類的關(guān)系
    2)前者主要表現(xiàn)為參數(shù)值的延續(xù),后者主要是方法、屬性的延續(xù)
    3)Spring中的Bean不可作為父Bean使用,而Java中子類可以當(dāng)成父類實例使用

    4.工廠Bean

    詳情參見P580-P582
    1.工廠Bean是實現(xiàn)FactoryBean接口的Bean

    2.FactoryBean接口提供了如下幾個方法:
    (1) T getObject():返回該工廠的自定義內(nèi)容
    (2) class<?> getObjectType():返回該工廠自定義內(nèi)容(java實例)的類型(實現(xiàn)類)
    (3) boolean isSingleton():返回自定義的java實例是否為單例模式

    3.工廠Bean配置在xml文件后,通過Spring容器的getBean()方法獲取時,得到的不是該Bean的實例,而是由開發(fā)者在getOject()方法里自定義的返回值,可能是一個數(shù)字,也可能是一個字符串,也可能是一個對象,所以此時配置工廠Bean時的id屬性指定的是getObject方法返回值在容器中的唯一標(biāo)識。

    4.如何返回工廠Bean本身?
    當(dāng)我們在用Spring容器的getBean()方法獲取工廠Bean時,在id前面加上"&"符
    號即可,如:

    ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml"); app.getBean("&factoryBeanId");

    5.強(qiáng)制初始化其他Bean
    如果某個類的初始化塊中使用了其他Bean,則這種依賴不夠直接,當(dāng)spring初始主調(diào)Bean時,可能會由于初始化塊中的其他Bean還未被初始化,則會拋出像空指針之類的異常。這時我們可通過depends-on屬性在初始化主調(diào)Bean前強(qiáng)制先初始化其他Bean,如:

    <bean id="person" class="com.test.Person" /> <bean id="test" class="com.test.Test" depends-on="person" />

    Spring中Bean的生命周期

    1. prototype作用域的Bean的生命周期
    當(dāng)Spring容器創(chuàng)建了prototype作用域的Bean實例之后,Bean實例完全交給客戶端代碼管理,容器不再跟蹤其生命周期,且每次客戶端請求該Bean時,都會新建一個實例。
    2. singleton作用域的Bean的生命周期
    每次客戶端請深圳市singleton作用域的Bean時,返回的都是同一個實例,spring容器負(fù)責(zé)跟蹤Bean實例的產(chǎn)生和銷毀。
    3. Spring如何管理Bean的生命周期
    1)依賴注入之后的行為,兩種方式:
    (1) 通過實現(xiàn)InitializingBean接口,然后利用afterPropertiesSet()方法處理
    (2) 通過<bean.../>元素的init-method屬性指定的方法處理

    <bean id="test" class="com.dfsj.Test" init-method="initMethod"><property name="username" value="peter"/> </bean> //這里的意思是,在完成Test注入之后,先執(zhí)行Test里的initMethod()方法 //如果(1)、(2)兩種方式都實現(xiàn)了,則在依賴注入之后,先執(zhí)行(1)的方法

    2)Bean銷毀之前的行為,兩種方式
    (1) 通過實現(xiàn)DisposableBean接口,然后利用destroy()方法處理
    (2) 通過<bean.../>元素的destroy-method屬性指定要執(zhí)行的處理方法
    如果(1)、(2)兩種方式都實現(xiàn)了,則在依賴注入之后,先執(zhí)行(1)的方法

  • 協(xié)調(diào)作用域不同步的Bean:參見P589-P591
  • Spring的其他依賴配置

    如果Spring框架用得熟練,別人給你任何一段Java代碼,你都能用spring的配置文件配置出來。前面了解了用<property.../>元素配setter方法、用<constructor-arg.../>元素配置有參構(gòu)造等等,下面我們來了解下如何配一個類的setter方法、普通方法、屬性、Field
    詳情參見P592~P599

    1. 使用PropertyPathFactoryBean獲取其他Bean的屬性值

    1)PropertyPathFactoryBean屬于工廠Bean,所以獲得其他Bean的屬性值的原理就是利用工廠Bean的getObject自定義返回值實現(xiàn)的,示例如:

    <bean id="test" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"><!-- person是Person類在容器中的id --><property name="targetBeanName" value="person"/> <property name="propertyPath" value="name"/> </bean>

    2)解釋上面配置:給PropertyPathFactoryBean的targetBeanName屬性注入指定Bean的id,給propertyPath屬性注入指定需要返回值的屬性,通過容器獲的getBean(“test”)方法獲取的值就是Person類的name屬性的值

    3)獲取指定Bean的具體某個屬性值的簡單方式:

    <bean id="son.age" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>//此時容器getBean方法得這樣寫:getBean("son.age"); //son是Son類在容器中的唯一標(biāo)識

    2. 使用FieldRetrivingFactoryBean獲取其他Bean的Field值

    首先要明確的是,這里所說的Field都是以public修飾的

    1)獲取靜態(tài)的Field的值,用targetClass屬性

    <bean id="test" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"><property name="targetClass" value="com.dfsj.Test"/> <property name="targetField" value="NAME"/> </bean>//或者: <bean id="test" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"><property name="targetClass" value="com.dfsj.Test"/> <property name="staticField" value="com.dfsj.Test.NAME"/> </bean>

    2)獲取實例Field,targetObject屬性

    <bean id="test" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"><property name="targetObject" ref="test"/> <property name="targetField" value="age"/> </bean>

    雖然2) 也能獲取靜態(tài)Field值,但不推薦這么用

    3. 使用MethodInvokingFactoryBean獲取其他Bean的方法的返回值

    1)獲取靜態(tài)方法返回值

    <bean id="jt" class="org.springframework.beans.factory.config. MethodInvokingFactoryBean"><property name="targetClass" value="com.dfsj.Test"/> <property name="targetMethod" value="staticMethodName"/><property name="arguments" ><list><value>"firstArgument"</value><value>"secondArgument"</value></list></property> </bean>

    2)獲取普通方法返回值

    <bean id="pu" class="org.springframework.beans.factory.config. MethodInvokingFactoryBean"><property name="targetObject" ref="test"/> <property name="targetMethod" value="staticMethodName"/><property name="arguments" value="傳一個參數(shù)" /> </bean>

    Spring基于xml Schema的簡化配置

    1. p:命名空間

    p:命名空間用于代替<property.../>元素進(jìn)行設(shè)值注入
    1.語法
    1)基本數(shù)據(jù)類型屬性:p:屬性名=“值”
    2)引用類型屬性:p:屬性名-ref=“引用Bean的id”
    2.導(dǎo)入p:命名空間

    http://www.springframework.org/schema/p

    3.示例

    <bean id="test" class="com.dfsj.Test" p:name="peter" p:person-ref="person"/> //等價于: <bean id="test" class=" com.dfsj.Test "><property name="name" value="peter"/ ><property name="person" ref="person"/ > </bean>
  • 注意
    如果Bean的屬性名以"-ref" 結(jié)尾,那么采用p:命名空間就會發(fā)生沖突
  • 2. c:命名空間

    c:命名空間用于代替<constructorg-arg.../>元素
    1. 導(dǎo)入c:命名空間
    http://www.springframework.org/schema/c
    2. 語法
    index是參數(shù)下標(biāo),從0開始
    1)基本數(shù)據(jù)類型:c:構(gòu)造參數(shù)名=“值” 或c:_index=“值”
    2)引用類型:c: 構(gòu)造參數(shù)名-ref=“引用Bean的id” 或 c:_index-ref=“其他Bean的id”
    3.示例

    <bean id="test" class="com.dfsj.Test" c:name="jhon" c:axe-ref="stoneAxe"/> //等價于: <bean id="test" class=" com.dfsj.Test ">< constructorg-arg value="jhon"/ >< constructorg-arg ref=" stoneAxe "/ > </bean>

    3. util命名空間

    1.constant
    用于獲取指定類的靜態(tài)Field值,它是FieldRetrievingFactoryBean的簡化配置,如:

    <util:constant id="person.age" static-field="AGE" />

    2.property-path
    用于獲取指定對象的getter方法的返回值,它是PropertyPathFactoryBean的簡化,如:

    <util:property-path id="testId" path ="person.name" />
  • list
    用于定義一個List集合,支持<value.../>、<ref.../>、<bean.../>等子元素,如:
  • < util:list id="schools" list-class="java.util.LinkedList ">< value>小學(xué)</value>< value>中學(xué)</value>< value>大學(xué)</value> </ util:list >

    4.set
    用于定義一個Set集合,支持<value.../>、<ref.../>、<bean.../>等元素,如:

    < util:set id="axes" set-class="java.util.HashSet ">< value>字符串值</value><bean class=" com.test.SteelAxe "/>< ref bean="stoneAxe"/> </ util:set >

    5.map
    用于定義一個Set集合,支持<entry.../>元素定義key-value對,如:

    < util:map id="sores" map-class="java.util.TreeMap ">< entry key="數(shù)學(xué)" value="88"/>< entry key="美術(shù)" value="80"/> </ util:map >

    6.properties
    用于加載一份資源文件,并創(chuàng)建一個Properties實例

    < util:properties id="test" location ="classpath:myProperties.properties "/>

    4.Spring的其他簡化配置的schema

  • spring-aop-4.0.xsd :用于簡化springAOP配置
  • spring-jee-4.0.xsd :用于簡化JavaEE配置
  • spring-jms-4.0.xsd :用于簡化JMS配置
  • spring-lang-4.0.xsd :用于簡化spring動態(tài)語言 配置
  • .spring-tx-4.0.xsd :用于簡化spring事務(wù) 配置
  • spring的兩種后處理器

    Bean后處理器:對容器中的Bean進(jìn)行后處理,進(jìn)行額外的加強(qiáng)
    容器后處理器:對IOC容器進(jìn)行后處理,用于增強(qiáng)容器的功能
    后處理器英文Post Processor

    1. Bean后處理器

  • 定義
    實現(xiàn)BeanPostProcessor接口的Bean就是Bean后處理器,它可對容器中的某一批Bean進(jìn)行增強(qiáng)處理

  • BeanPostProcessor接口有如下兩個方法:
    下同的bean是要處理的Bean實例,name是該Bean配置的id
    1)Object postProcessBeforeInitialization(Object bean, String name) throws Exception
    在注入依賴之后初始化Bean之前調(diào)用

  • Object postProcessAfterInitialization(Object bean, String name) throws Exception
    如果指定了init-method屬性,則在它指定的方法之后執(zhí)行
  • 兩個常見的Bean后處理器
    1)BeanNameAutoProxyCreator:根據(jù)實例Bean的name屬性創(chuàng)建Bean實例的代理
    2)DefaultAdvisorAutoProxyCreator:根據(jù)提供的Advisor對容器中的所有Bean他建代理

  • Bean后處理器會對容器中的所有Bean進(jìn)行后處理(在方法里可過濾掉某些不需要處理的Bean),所以在配置Bean后處理器可以不用指定id。如果用BeanFactroy作為Spring容器,則程序必須先獲取Bean后處理器實例,然后手動注冊,詳情參見P617

  • Bean后處理器與其他初始化方法的執(zhí)行順序
    注入完成
    Bean后處理器的postProcessBeforeInitialization方法
    InitializingBean接口的afterPropertiesSet方法
    init-method屬性指定的方法
    Bean后處理器的postProcessAfterInitialization方法

  • 2. 容器后處理器

  • 定義
    實現(xiàn)BeanFactoryPostProcessor接口的類就是容器后處理器,它負(fù)處理容器本身
  • BeanFactoryPostProcessor接口的方法
    void postProcessBeanFactory(ConfigurableListableBeanFactory bean) throws BeansException;
  • 常用的幾個容器后處理器
    1)PropertyPlaceholderConfigurer:屬性占位符配置器
    2)PropertyOverrideConfigurer:重寫占位符配置器
    3)CustomAutowireConfigurer:自定義自動裝配的配置器
    4)CustomScopeConfigurer:自定義作用域的配置器
  • 和Bean后處理器一樣,容器后處理器配置在Spring容器中時,如果以ApplicationContext作為Spring容器,則容器會自動檢測到容器后處理器,所以不需要配置id,但如果使用BeanFactory作為Spring容器,則必須手動注冊
  • 如果配置了多個容器后處理器,則可要求容器后處理器必須實現(xiàn)Ordered接口,然后指定order屬性
  • 3.容器后處理器之屬性占位符配置器

  • PropertyPlaceholderConfigurer這個屬性占位符配置器可讀取Properties文件里的鍵值對,先加載properties文件,再用EL表達(dá)式取值,如:
  • Properties文件代碼:
    username=“Peter”
    password=“123456”
  • beans.xml文件配置代碼:
  • <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="locations" > <list><!-- 如果有多個配置文件,可依次羅列出來 --><value>myPropertyFile.properties</value></list></property> </bean> <bean id="user" class="com.dfsj.User"><property name="name" > ${username} </property><property name="password" > ${password} </property> </bean>

    4.基于XML Schema的簡化配置

    <context:property-placeholder location="classpath:myPropertyFile.properties"/>

    4.容器后處理器之重寫占位符配置器

  • PropertyOverrideConfigurer這個重寫占位符配置器,較屬性占位符配置器多了一個功能,那就是Properties文件里的鍵值對的值可覆蓋spring的xml配置文件里的值,前提需要Properties文件里的鍵值對滿足以下格式:
    容器中配置的Bean的id.該Bean的屬性 = 值
  • 示例
  • //1.Properties文件代碼:user.username="peter"user.password="123456"//2.對應(yīng)beans.xml代碼: <bean class=" org.springframework.beans.factory.config.PropertyOverrideConfigurer"><property name="locations" > <list><!-- 如果有多個配置文件,可依次羅列出來 --><value>myPropertyFile.properties</value></list></property> </bean> <!-- 下面Bean里的屬性注入的值會被覆蓋 --> <bean id="user" class="com.dfsj.User"><property name="name" > 張三 </property><property name="password" > 654321 </property> </bean>

    3.基于XML Schema的簡化配置

    <context:property-override location="classpath:myPropertyFile.properties"/>

    Spring 注解之零配置

    1.指定SpringBean的注解

  • 當(dāng)不用xml配置文件將Java類配置成Spring容器的Spring Bean時,我們就需要以下幾個注解來指定:
    @Component :標(biāo)注Java類為普通Spring Bean
    @Controller :標(biāo)注Java類為控制器組件
    @Service :標(biāo)注Java類為業(yè)務(wù)邏輯組件
    @Repository :標(biāo)注Java類為DAO組件
  • 為指定的Spring Bean定義名字(相當(dāng)于之前配置文件里的id值)
    默認(rèn)spring bean的名字是對應(yīng)Java類的類名小寫首字母
    自定義名字,如: @Component(“myName”)
  • 2.搜索Spring Bean

  • 當(dāng)不用xml配置時,指定成Spring Bean的Java類還需要掃描搜索才能找到,這就需要在xml配置文件中指定掃描的包路徑,此時需要導(dǎo)入context:命名空間:
  • xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation=" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0-xsd"<!-- 掃描下面包路徑,找到所有springBean--><context:component-scan base-package="包路徑" /> 這樣在創(chuàng)建Spring容器時,spring容器會掃描搜索上面路徑下的所有被標(biāo)注成Springbean的Java類,然后創(chuàng)建對應(yīng)的實例放在Spring容器中。
  • 通過為< component-scan.../>元素添加<include-filter.../>或<exclude-filter.../>元素來指定Spring Bean類,即使該Java類沒有使用Annotation
    滿足<include-filter.../>規(guī)則的Java類會被當(dāng)成Spring Bean
    滿足< exclude-filter.../>規(guī)則的Java類不會被當(dāng)成Spring Bean
    上面兩元素都要求指定如下兩屬性:
    type:指定過濾器類型,有4種類型:
    annotation:此時表達(dá)式需要指定一個Annotation類完整名
    assignable:此時表達(dá)式需要指定一個Java類
    regex:此時表達(dá)式需要指定.一個正則表達(dá)式
    aspectj:此時表達(dá)式需要指定一個AspectJ過濾器,如:org.example…*Service+
    expression:指定過濾器需要的表達(dá)式
    示例
  • <!-- 啟動包掃描功能,使帶有@Controller、@Service、@Repository、@Component等注解的類成為Spring容器的Bean --> <context:component-scan base-package="com.User" > <context:include-filter type="regex" expression=".*Dao"/><context:include-filter type="regex" expression=".*Service"/> </context:component-scan>

    3.配置依賴的@Resource注解

  • @Resource注解直接來源于JavaEE規(guī)范,其作用類似<property.../>元素的ref
  • @Resource注解既能修飾setter方法,也能修飾Field。若不指定name值,則默認(rèn)以變量名為name值
  • 如果@Resource修飾的是接口Field,在沒有指定name時按byType方式注入,如果該接口有多個實現(xiàn)類時,則spring容器會因為不知具體去找哪個類而報錯。所以,如果只有其中一個實現(xiàn)類被指定為Spring Bean時不指定名字則不會報錯。
  • 4.指定Bean作用域的@Scope注解

  • Spring Bean的默認(rèn)作用域是singleton

  • 定義Spring Bean作用域,如:

    @Scope("prototype")@Component("user")public class User { ...}
  • 自定義作用域解析器(不再基于Annotation的方法來指定作用域)
    自定義解析器類必須實現(xiàn)ScopeMetadataResolver接口,還要配置在< component-scan.../>元素中,如:

  • <context:component-scan base-package="包路徑" scope-resolver="自定義解析器類"/>

    5 定制SpringBean生命周期行為的注解

    @PostConstruct、@PreDestroy都直接來源于JavaEE規(guī)范,都用于修飾方法
    @PostConstruct修飾的方法在完成注入之后回調(diào),如果被它修飾的類實現(xiàn)了InitializingBean接口,則@PostConstruct修飾的方法在afterPropertiesSet方法之前執(zhí)行
    @PreDestroy 修飾的方法在Bean銷毀前回調(diào)執(zhí)行

    6 自動裝配和精裝配的注解

  • @AutoWired注解用于自動裝配,可修飾setter方法、普通方法、Field、構(gòu)造器等
  • @AutoWired注解是通過byType方式裝配注入的
  • 如果@AutoWired要裝配的是數(shù)組或集合類型對象時,spring會搜索容器中所有該類型的實例注入到其中,且集合類型時必須指明泛型。
  • 如果@AutoWired要裝配的是接口,且該接口在spring容器中有多個實例,則此時根據(jù)@AutoWired 的byType方式裝配就會拋異常了,因為spring不知道具體要裝配哪個,這時我們可以通過@Qualifier注解來精確裝配,如:
  • @Autowired @Qualifier("test") private TestInter test;

    7 Spring的其他注解

  • @DependsOn :修飾Bean類或方法,用于在初始化其修飾的Bean前強(qiáng)制初始化其他Bean
    @DependsOn({“chinese”,“japanese”}) //在初化Person類前初化chinese、japanese
    @ DependsOn(“chinese”) //只強(qiáng)制初始化一個Bean
  • @Lazy :是否要在創(chuàng)建Spring容器時預(yù)初始化該Bean,默認(rèn)false
    @Lazy(true) :表示要延遲初始化該Bean,即不預(yù)初始化。
  • Spring的AOP

    為什么需要AOP?
    面向?qū)ο缶幊?#xff08;OOP)里,如果有共用的代碼我們一般的做法是提取出一個公共方法供大家調(diào)用,這種方式并沒有完全解耦,比如說有一個方法之前調(diào)用過公共代碼,現(xiàn)需求變成該方法不需要調(diào)用公共代碼了,此時我們還得去該方法里刪除公共代碼塊。
    而面向切面編程(AOP)不止能提取出公共代碼,而且還能控制哪些方法調(diào)用該公共代碼,其他方法根本不知道發(fā)生了什么變化,這就實現(xiàn)了完全的解耦。所有AOP很有用。
    比如事務(wù)管理、安全檢查、緩存、對象池管理等等都是很好的AOP思想。
    spring的AOP也需要jar包:aspectjweaver.jar和aspectjtr.jar
    在Spring的AOP中,連接點(切入點)總是方法的調(diào)用

    1 基于注解管理的AOP

    1.1 使用步驟

  • 啟動@AspectJ支持
    在spring配置文件中加入下面配置:
  • <aop:aspectj-autoproxy /> //也可用以下方式啟動: <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/> //AnnotationAwareAspectJAutoProxyCreator是一個Bean后處理器,為spring容器中的bean生成AOP代理

    2.定義切面Bean
    定義切面Bean用@Aspect注解,如:

    @Aspectpublic class LogAspect{....}

    定義好的切面Bean也需要掃描成Spring Bean,有如下兩種方式:
    1):在切面Bean里加入@Component注解
    2):用include-filter元素:

    <context:component-scan base-package="com.*" ><context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/> </context:component-scan>

    3.定義一個要被增強(qiáng)處理的類

    @Component public class User {public void say(){System.out.println("被增強(qiáng)處理的方法");} }

    4.指定切入點和增強(qiáng)處理方法

    @Aspect @Component public class BeforeAop {//訪問修飾符public 可省略@Before("execution(public void com.User.User.say())")public void before(){System.out.println("在之前切入點之前的增強(qiáng)處理");} }

    execution方法是用來指定切入點的,這和AspectJ的語法一樣。
    由于通常的增強(qiáng)處理是對一批方法的處理,所以需要通匹配符*,如下:

    @Before("execution(* *.*(..))")

    根據(jù)Before Aop里的示例可知,第一個*表示返回值為任意類型,第二個*表示所有類,第三個*表示所有方法,括號里的…表示任意參數(shù)
    如果是某個包及其子包的所有類的所有方法都要匹配,則應(yīng)如下:

    @Before("execution(* com.aops..*.*(..))")

    …代表零個或多個
    1.2 簡單示例

    //1.配置文件代碼: <?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:mvc="http://www.springframework.org/schema/mvc"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"><!-- Aspectj支持 --><aop:aspectj-autoproxy /><!-- 啟動包掃描功能--><context:component-scan base-package="com.*" > <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect" /></context:component-scan> </beans> //2. 定義增強(qiáng)處理的切面類和切入點@Aspect@Componentpublic class BeforeAop {@Before("execution(public void com.User.User.say())")public void before(){System.out.println("在切入點之前的增強(qiáng)處理");}} //3. 定義一個要被增強(qiáng)處理的類@Componentpublic class User {public void say(){System.out.println("被增強(qiáng)處理的方法");}} //4.測試:public class Test {public static void main(String[] args) {ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml"); User t = (User) app.getBean("user");t.say();}}

    執(zhí)行結(jié)果:
    在切入點之前的增強(qiáng)處理
    被增強(qiáng)處理的方法

    1.3 定義After增強(qiáng)處理

  • 示例
  • @After("execution(* *.*(..))")public void after(){System.out.println("在切入點之后處理");}

    2.After增強(qiáng)處理與AfterReturning 增強(qiáng)處理的區(qū)別:
    After增強(qiáng)處理不論目標(biāo)方法是否正常結(jié)束,都會調(diào)用處理
    AfterReturning 只在目標(biāo)方法成功完成后才處理調(diào)用
    1.4 定義AfterReturning 增強(qiáng)處理

  • AfterReturning增強(qiáng)處理是在目標(biāo)方法返回值后進(jìn)行增強(qiáng)處理,比After晚招牌處理。它用@AfterReturning注解標(biāo)注,該注解有兩常用屬性:
    pointcut/value:這兩屬性作用一樣,用于指定切入點的表達(dá)式
    returning:指定一個返回值形參名,該增強(qiáng)處理定義的方法可通過該形參名來訪問目標(biāo)方法的返回值
    還有一屬性argNames:參數(shù)列表參數(shù)名
  • 示例:
  • @AfterReturning(pointcut="execution(* *.*(..))",returning="objss") public void returnMethod(Object objss){System.out.println(objss); }

    1.5 定義AfterThrowing增強(qiáng)處理
    類似于AfterReturning增強(qiáng)處理,例:

    @AfterThrowing(throwing="ex", pointcut="execution(* *.*(..))") public void doRecoverActions(Throwable ex) { System.out.println("目標(biāo)方法中拋出的異常:" + ex); System.out.println("模擬拋出異常后的增強(qiáng)處理..."); }

    1.6 定義Around增強(qiáng)處理
    Around 增強(qiáng)處理近似等于 Before 增強(qiáng)處理和 AfterReturning 增強(qiáng)處理的總和。它既可在執(zhí)行目標(biāo)方法之前織入增強(qiáng)操作,也可以之后織入。它既可改變執(zhí)行目標(biāo)方法的參數(shù)值,也可改變目標(biāo)方法之后的返回值。甚至能控制目標(biāo)方法什么時候執(zhí)行。如:

    @Around("execution(* com.aops.User.getHeight(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("---around開始-------");Object[] arg = joinPoint.getArgs();//獲得要傳給目標(biāo)方法的所有參數(shù)argArray[0] = "改變第一個參數(shù)的值";//改變傳入目標(biāo)方法的參數(shù)Object o = joinPoint.proceed(arg);//調(diào)用目標(biāo)方法,并得到返回值System.out.println(obj);//打印返回值 System.out.println(argArray.toString());//打印參數(shù)System.out.println("---around結(jié)束-------");return o+"調(diào)用目標(biāo)方法得到的結(jié)果";//改變調(diào)用目標(biāo)方法的返回值 }

    ProceedingJoinPoint是JointPoint的子類,其他增強(qiáng)處理的方法里如要想獲得傳入?yún)?shù)就得通過JointPoint的getArgs方法。
    注:只有Around增強(qiáng)處理能改變目標(biāo)方法參數(shù)。

    1.7 相同增強(qiáng)處理執(zhí)行順序
    1、如果是同一個切面類里有兩個相同的增強(qiáng)處理在同一個連接點被織入時,Spring Aop將隨機(jī)織入這兩個增強(qiáng)處理。
    2、 如果是兩個切面類里有相同的增強(qiáng)處理在同一個連接點被織入時,具有高優(yōu)先級的增強(qiáng)處理將先被織入。
    3、指定優(yōu)先級的兩個方法:
    1)讓切面類實現(xiàn)org.springframework.core.Ordered接口,然后實現(xiàn)int getOrder()方法,該方法的返回值越小,優(yōu)先級越高
    2)用@Order注解修飾切面類,此時可指定一個int型的value,值越小優(yōu)先級越高

    1.8定義切入點
    AspectdJ和Spring都允許定義切入點,即為一個切入點表達(dá)式起一個名字,從而允許在多個增強(qiáng)處理中能重復(fù)調(diào)用。
    1、定義:用@Pointcut注解修飾一個返回類型為void的空方法,方法名即為切入點名字。

    @Pointcut("execution(* *.*(..))") public void myPointcut(){ }

    如果希望該切入點只能在本切面類使用,則需將public改為private
    2、引用:
    1) 在同一個切面類里可直接引用,如:

    @After(value="myPointcut()") public void after(){ System.out.println("after......"); }

    2) 如果是引用不同切面類里的切入點,則需要加上其他切面類的類名,如:

    @After(value="OtherAdvice.myPointcut()") public void after(){System.out.println("after......"); }

    1.9 切入點指示符

  • execution:匹配執(zhí)行方法的連接點,格式如下:
    execution(訪問修飾符 目標(biāo)方法返回值類型 目標(biāo)所屬類.目標(biāo)方法名(形參列表)目標(biāo)拋出異常)
    execution(public * * (…)) //匹配任意public方法
    execution(* set*(…)) //匹配任何方法名以set開始的方法
    execution(* com.aop.User.(…)) //匹配User類的所有方法
    execution( com..(…)) //匹配一個包中任意類的任意方法
  • within:限定匹配特定類型的連接點
    within(com.aop.) //匹配aop包中的任意方法
    within(com.aop…) //匹配aop包及其子包的任意方法
  • this:匹配AOP代理
    this(com.aop.UserInter) //匹配AOP實現(xiàn)UserInter接口,注意是AOP,不太理解
    4.target:匹配目標(biāo)對象必須是指定類型
    target(com.aop.User)
  • args:對連接點(目標(biāo)方法)的參數(shù)類型進(jìn)行限制
    args(java.lang.String) //只匹配傳入?yún)?shù)是String類型,且只傳一個參數(shù)的所有目標(biāo)方法
    這與execution(* *(java.lang.String))不同,execution里表示只匹配只包含一個String類型形參的方法
    6.bean:只匹配指定Bean實例的目標(biāo)方法
    bean(*Service) // 匹配名字以Service結(jié)尾的bean實例
    其中名字是Bean的id或name
    1.10 切入點組合表達(dá)
    &&:同時匹配
    ||:只需要滿足一個切入點表達(dá)式即可
    !:匹配不是該切入點表達(dá)式的其他連接點
    示例:
  • @Aspect @Component public class BeforeAop {@Before("execution(!public void com.User.User.*())")public void before(){System.out.println("在切入點之前的增強(qiáng)處理");} }

    只要不是User類的目標(biāo)方法都能被匹配

    2基于xml配置的AOP

    不推薦使用XML配置方式,推薦使用@Aspect
    2.1 注意
    1、基于注解的AOP配置能被Spring AOP和AspectJ同時支持
    2、使用 <aop:config…/>元素可能與Spring的自動代理方式?jīng)_突,因此,要么全部使用<aop:config…/>配置方式,要么全部使用自動代理方式,不能二者混用
    3、XML配置方式僅支持”singleton”的切面Bean,不能在xml中組合多個命名連接點的聲明
    4、XML配置方式時,所有關(guān)于AOP的信息都必須配在<aop:config…/>元素中
    5、如果<aop:config…/>元素里同時有<aop:pointcut…/>、<aop:advisor…/>、<aop:aspect…/>元素時,必須是pointcut、advisor、aspect這樣的出現(xiàn)順序。
    6、如果是要增強(qiáng)處理一個有返回值的目標(biāo)方法,則對應(yīng)切面類的增強(qiáng)方法也必須寫上返回值,否則系統(tǒng)一直處于等待狀態(tài)中。
    7、XML方式的組合運算符:and(相當(dāng)于&&)、or(相當(dāng)于||)、not(相當(dāng)于!)
    8、遺留問題:<aop:advisor…/>是什么?跟spring自動代理有什么關(guān)系?什么是自動代理?
    2.2 示例與說明
    1、切面類:

    public class AspectAdvice {public void after(){System.out.println("調(diào)用目標(biāo)方法結(jié)束后回調(diào)用,無論成與否");} public void before(){System.out.println("before......");} public Object afterReturning(Object obj){System.out.println("成功返回后回調(diào)"+obj);return obj;} public Object around(ProceedingJoinPoint jp) throws Throwable{System.out.println("調(diào)用目標(biāo)方法前執(zhí)行增強(qiáng)處理...");Object[] arg =jp.getArgs(); //得到目標(biāo)方法的形參列表Object obj = jp.proceed(arg); // 調(diào)用目標(biāo)方法System.out.println("調(diào)用目標(biāo)方法這后執(zhí)行的增強(qiáng)處理..."); return obj;} }2、配置文件: <!-- 注入切面類 --> <bean id="advice" class="com.aops.AspectAdvice" /> <aop:config><!-- 配置切入點,該配置一定要出現(xiàn)在aop:aspect前面 --><aop:pointcut id="myPointcut" expression="execution(* com.aops.User.getHeight(..))"/><!-- order屬性指定優(yōu)先級,值越小,優(yōu)先級越高 --><aop:aspect id="aspect" ref="advice" order="1"><!-- method屬性指定調(diào)用切面類的哪個增強(qiáng)方法 --><aop:after method="after" pointcut="execution(* com.aops.User.*(..))"/><!-- pointcut屬性指定切入表達(dá)式 --><aop:before method="before" pointcut="execution(* com.aops.User.*(..))"/><!-- returning指定接收返回參數(shù)的參數(shù)名 --><aop:after-returning returning="obj" pointcut-ref="myPointcut" method="afterReturning"/><!-- pointcut-ref屬性指定配置的切入表達(dá)式id --><aop:around method="around" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config>

    注:當(dāng)<aop:pointcut…/>元素是<aop:aspect >的子元素時,說明該切入點只能被當(dāng)前切面類使用

    Spring的事務(wù)

  • 對于不同的持久層訪問技術(shù),編程式事務(wù)提供了一致的事務(wù)編程風(fēng)格,通過模板化操作一致地管理事務(wù)。
  • 聲明式事務(wù)是基于AOP實現(xiàn)的
  • 傳統(tǒng)的事務(wù)編程與具體的事務(wù)操作代碼耦合,如果切換事務(wù)策略時,必須手動更改代碼,而使用Spring管理策略時則就會
  • Spring的事務(wù)機(jī)制是一種典型的策略模式,它本身沒有任何事務(wù)支持,只是負(fù)責(zé)包裝底層的事務(wù)
  • 1. Spring支持的事務(wù)策略

    spring各種全局事務(wù)、局部事務(wù)示例配置,參見P683-P685

    1.1 全局事務(wù)

  • 全局事務(wù)由應(yīng)用的服務(wù)器管理,需要底層服務(wù)器支持JTA(Java Transaction API)
  • 全局事務(wù)可以跨多個事務(wù)性資源(典型的例子是關(guān)系數(shù)據(jù)庫和消息對列)
  • 不論采用哪種持久層訪問技術(shù),只要使用JTA全局事務(wù),Spring事務(wù)管理的配置就完全一樣,都采用全局事務(wù)管理策略。
    ###1.2 局部事務(wù)
  • 局部事務(wù)與底層采用的持久化技術(shù)有關(guān),當(dāng)采用了JDBC持久化時,需要用Connection對象來操作事務(wù),當(dāng)采用了Hibernate持久化時,需要用Session對象來操作事務(wù)。
  • 由于局部事務(wù)事務(wù)不需要應(yīng)用服務(wù)器參與事務(wù)管理,所以不能保證跨多個事務(wù)資源的事務(wù)的正確性,但實際情況是,大部分應(yīng)用都是使用單一的事務(wù)性資源
  • 1.3 PlatformTransactionManager

  • Spring事務(wù)策略是通過PlatformTransactionManager接口實現(xiàn)的,它是核心。當(dāng)?shù)讓硬捎貌煌某志没中g(shù)時,系統(tǒng)只需要使用該接口的不同實現(xiàn)類即可。
  • PlatformTransactionManager接口包含一個getTransaction(TransactionDefinition define)方法,該方法返回一個TransactionStatus對象,該對象就表示一個事務(wù),它可簡單的控制和查詢事務(wù)。該事務(wù)可能是一個新的事務(wù),也可能是已經(jīng)存在的事務(wù),如果當(dāng)前執(zhí)行線程已經(jīng)處理事務(wù)管理下,則返回當(dāng)前線程的事務(wù),否則新建一個事務(wù)對象返回。它有如下方法:
    isNewTransaction():判斷是否是一個新事務(wù)
    setRollbackOnly():設(shè)置回滾
    isRollbackOnly():判斷是否有回滾標(biāo)志
  • TransactionDefinition 接口用于定義事務(wù)規(guī)則,如隔離級別、超時、只讀狀態(tài)等等….
  • 2 Spring的兩種事務(wù)管理方式

    2.1 編程式配置事務(wù)

  • 編程式通過寫代碼的方式得到PlatformTransactionManager實例,然后設(shè)置開始事務(wù)、提交事務(wù)和回滾事務(wù)。
    2.2 聲明式配置事務(wù)
  • 聲明式配置不寫任何Java代碼,只需在XML文件中通過事務(wù)代理(AOP代理的一種)來配置。具體實現(xiàn)原理是,在目標(biāo)方法執(zhí)行前織入開始事務(wù),在目標(biāo)方法執(zhí)行之后織入結(jié)束事務(wù)。推薦使用聲明式配置事務(wù)
  • spring用tx:命名空間的<tx:advice…/>元素來配置事務(wù)的增強(qiáng)處理,然后用<aop:advisor…/>元素啟用自動代理
    3.注意:
    spring支持接口代理,也支持對具體的類生成代理。
    如果一個具體的實現(xiàn)類如UserDaoImpl沒有實現(xiàn)接口,按如下配置沒有問題;但是,如果UserDaoImpl類實現(xiàn)了接口,則下面的配置將會報錯,要解決這個問題,需要在配置文件中設(shè)置proxy-target-class屬性的值為true,如下:
  • <aop:aspectj-autoproxy proxy-target-class="true"/>

    這是因為,Spring默認(rèn)采用JDK動態(tài)代理,而CGLIB代理是面向接口代理的,二者區(qū)別需查閱相關(guān)資料。
    2.3 示例:
    對應(yīng)配置文件:

    <?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:util="http://www.springframework.org/schema/util"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-4.1.xsd"> <!-- 掃描springbean --><context:component-scan base-package="com.transaction" /><!-- 定義數(shù)據(jù)源Bean,使用C3P0數(shù)據(jù)源,并配置相關(guān)信息 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"destroy-method="close" p:driverClass="com.mysql.jdbc.Driver"p:jdbcUrl="jdbc:mysql://localhost:3306/db1"p:user="root"p:password="root"p:maxPoolSize="40"p:minPoolSize="2"p:initialPoolSize="2"p:maxIdleTime="30"/><!-- 配置JDBC數(shù)據(jù)源的局部事務(wù)管理器:使用DataSourceTransactionManager類該類實現(xiàn)了PlatformTransactionManager接口,是針對采用數(shù)據(jù)源連接的特定實現(xiàn)所以,也需要注入DataSource的引用 --><bean id="transactionManagerId" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/> <!-- 配置事務(wù)增強(qiáng)處理,指定事務(wù)管理器,transaction-manager屬性的默認(rèn)值是:transactionManager --> <tx:advice id="txAdvice" transaction-manager="transactionManagerId"><!-- 配置詳細(xì)的事務(wù) --><tx:attributes><!-- 所有以get開頭的方法只能讀 --><tx:method name="get*" read-only="true" /><!-- 其他方法設(shè)置默認(rèn)隔離級別,超時為5秒 --><tx:method name="*" isolation="READ_COMMITTED"propagation="REQUIRED" timeout="5" /><!-- propagation屬性用于指定事務(wù)傳行為,它的值是枚舉值,具體每個值對應(yīng)的行為是什么,請參考P687或百度 。isolation指定事務(wù)隔離級別rollback-for指定觸發(fā)事務(wù)回滾的異常類(須是全限定類名),多個異常類時用逗號隔開no-rollback-for 指定不觸發(fā)事務(wù)回滾的異常類--></tx:attributes></tx:advice><!-- 如果UserDaoImpl實現(xiàn)了接口,則必須加入以下代碼強(qiáng)制實現(xiàn)CGLIB動態(tài)代理,cglib可以在運行期擴(kuò)展Java類與實現(xiàn)Java接口。cglib封裝了asm,可以在運行期動態(tài)生成新的class(默認(rèn)是JDK動態(tài)代理),詳情可百度AOP的兩種代理方式 --><!-- <aop:aspectj-autoproxy proxy-target-class="true"/> --><!-- 配置AOP元素 --><aop:config><!-- 配置切入點:即AOP適用的范圍 --><aop:pointcut id="point" expression="execution(* com.transaction.UserDaoImpl.*(..))"/><!-- 在切入點 應(yīng)用txAdvice增強(qiáng)處理--><aop:advisor advice-ref="txAdvice" pointcut-ref="point"/></aop:config></beans>

    對應(yīng)Java邏輯代碼:

    @Repository("userDao") public class UserDaoImpl{@Resource(name="dataSource")private DataSource dataSource;//插入操作public void insertData(){JdbcTemplate jt = new JdbcTemplate(dataSource);jt.update("insert into workers_info values(id,workername) values(1,你好)"); }//讀取操作public void getData(){ JdbcTemplate jt = new JdbcTemplate(dataSource);jt.execute("select * from workers_info");//該方法在事務(wù)配置里設(shè)置為 只讀,執(zhí)行下面的非讀操作會報錯//jt.update("insert into workers_info values(id,workername) values(1,你好)");} }

    spring還可以為不同的方法指定不同的事務(wù)策略,具體參見P691
    spring還允許將事務(wù)放在Java類中定義(@Transaction注解),具體參見P692

    3 spring事務(wù)的傳播屬性

    Spring補(bǔ)充知識

    ApplicationContextAware

    參考:https://www.jianshu.com/p/4c0723615a52

    注解@ControllerAdvice

    POJO:簡單的Java對象即JavaBean
    EJB:服務(wù)器端組件模型

    本人將知識都生成了圖片,地址:https://img-blog.csdn.net/20160930173240547

    總結(jié)

    以上是生活随笔為你收集整理的spring知识概要的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。