spring知识概要
目錄
文章目錄
- **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中類(lèi)的繼承的區(qū)別:
- 4.工廠Bean
- **Spring中Bean的生命周期**
- **Spring的其他依賴配置**
- 1. 使用PropertyPathFactoryBean獲取其他Bean的屬性值
- 2. 使用FieldRetrivingFactoryBean獲取其他Bean的Field值
- 3. 使用MethodInvokingFactoryBean獲取其他Bean的方法的返回值
- **Spring基于xml Schema的簡(jiǎn)化配置**
- 1. p:命名空間
- 2. c:命名空間
- 3. util命名空間
- 4.Spring的其他簡(jiǎn)化配置的schema
- **spring的兩種后處理器**
- 1. Bean后處理器
- 2. 容器后處理器
- 3.容器后處理器之屬性占位符配置器
- 4.容器后處理器之重寫(xiě)占位符配置器
- **Spring 注解之零配置**
- 1.指定SpringBean的注解
- 2.搜索Spring Bean
- 3.配置依賴的@Resource注解
- 4.指定Bean作用域的@Scope注解
- 5 定制SpringBean生命周期行為的注解
- 6 自動(dòng)裝配和精裝配的注解
- 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ǔ)充知識(shí)
- ApplicationContextAware
- 注解@ControllerAdvice
Spring基礎(chǔ)
1) 低侵入式,代碼污染低
2) 獨(dú)立于各種應(yīng)用服務(wù)器
3) IOC降低了業(yè)務(wù)對(duì)象替換的復(fù)雜性,降低了組件之間的耦合
4) AOP支持通用任務(wù)如日志、事務(wù)、安全等的集中處理
5) ORM和DAO提供了與第三方持久框架的良好整合,并簡(jiǎn)化了底層數(shù)據(jù)庫(kù)的訪問(wèn)
6) 開(kāi)發(fā)者可自由選擇Spring框架的部分或全部,不像有些框架得全部引用
a) org.springframework.core
b) org.springframework.beans
c) org.springframework.content
d) org.springframework.expression
spring容器還依賴于common-logging 這個(gè)JAR包
我們將Bean配置在XML文件里后,在創(chuàng)建Spring容器后,Spring容器就開(kāi)始解析Xml文件。當(dāng)解析到<bean…/>元素里class屬性的完整類(lèi)名時(shí),就會(huì)利用反射機(jī)制實(shí)例化一個(gè)對(duì)象,當(dāng)解析到<property…/>元素時(shí),就會(huì)執(zhí)行該對(duì)象的setter方法,其中name屬性決定執(zhí)行哪個(gè)setter方法,value或ref屬性決定setter方法的傳入?yún)?shù)。最后在完成注入后,將<bean…/>元素里的id屬性值和創(chuàng)建的對(duì)象以鍵值對(duì)的形式存在Spring容器中,這樣Spring容器就可管理Bean了。
a) 當(dāng)傳入?yún)?shù)是基本數(shù)據(jù)類(lèi)型或String類(lèi)型時(shí)用vlaue
b) 當(dāng)傳入?yún)?shù)是其他Bean時(shí),則用ref(即引用類(lèi)型用ref)
常用ApplicationContext接口的實(shí)現(xiàn)類(lèi)來(lái)獲取,該接口主要有以下兩個(gè)方法:
a) Object getBean(String name):獲取容器中id為name的Bean實(shí)例
b) T getBean(String id,Class<T> type):根據(jù)id名和Bean類(lèi)型獲取該Bean
ApplicationContext接口的主要實(shí)現(xiàn)類(lèi):
a) ClassPathXmlApplicationContext :從類(lèi)加載路徑下搜索配置文件
b) FileSystemXmlApplicationContext:從文件系統(tǒng)的相對(duì)或絕對(duì)路徑下搜索配置文件
c) AnnotationConfigWebApplicationContext:使用注解替換xml配置文件時(shí)使用【單測(cè)時(shí)用比較方便】
示例:
10.總結(jié)
有了spring后,程序可不再使用new來(lái)創(chuàng)建對(duì)象了
Spring容器
a) 在創(chuàng)建容器時(shí)就初始化容器中的Bean,可通過(guò)<bean…/>元素的lazy-init=”true”取消
b) 因繼承了MessageSource接口所以支持國(guó)際化
c) 支持資源訪問(wèn),如URL和文件
d) 支持事件機(jī)制
e) 可同時(shí)加載多個(gè)配置文件
f) 能通過(guò)聲明方式啟動(dòng)并創(chuàng)建Spring容器
a) 常用實(shí)現(xiàn)類(lèi):
ClassPathXmlApplicationContext:從類(lèi)加載路徑下搜索配置文件
FileSystemXmlApplicationContext:從文件系統(tǒng)的相對(duì)或絕對(duì)路徑下搜索配置文件
AnnotationConfigApplicationContext:使用Java配置替換xml配置文件時(shí)使用
b) 在web應(yīng)用中常用的實(shí)現(xiàn)類(lèi):
XmlWebApplicationContext:
AnnotationConfigWebApplicationContext:使用注解替換xml配置文件時(shí)使用
ApplicationContext app = new ClassPathXmlApplicationContext(“beans.xml”);
當(dāng)有多個(gè)配置文件時(shí),可在classpath后面使用通配符“*”
Spring創(chuàng)建Bean的3種方式
a) 調(diào)用構(gòu)造器
b) 調(diào)用靜態(tài)工廠方法
c) 調(diào)用實(shí)例工廠方法
a) class:指定靜態(tài)工廠類(lèi)的類(lèi)名
b) factory-method:指定創(chuàng)建實(shí)例的靜態(tài)工廠方法
需要注意的是,靜態(tài)工廠方法的參數(shù)通過(guò)<constructor-arg…/>元素配置,而新建對(duì)象的屬性的值通過(guò)<property…/>元素設(shè)置
3.使用實(shí)例工廠方法創(chuàng)建Bean時(shí),<bean…/>元素需要指定如下兩屬性:
a) factory-bean:指定工廠類(lèi)實(shí)例,即工廠類(lèi)在配置文件中的id
b) factory-method:指定實(shí)例工廠創(chuàng)建實(shí)例方法
4.靜態(tài)工廠方法與實(shí)例工廠方法的區(qū)別:
不同點(diǎn):
a) 靜態(tài)工故事有class屬性,指定的是靜態(tài) 工廠類(lèi)的類(lèi)名,而實(shí)例工廠是用factory-bean屬性指定工廠類(lèi)在配置文件中的id
b) 靜態(tài)工廠方法創(chuàng)建Bean實(shí)例的方法是靜態(tài)的
相同點(diǎn)
a) 都需要用factory-method指定創(chuàng)建Bean實(shí)例的方法
b) 工廠方法里的參數(shù)都必須通過(guò)<constructor-arg…/>元素來(lái)配置
c) 給新創(chuàng)建的Bean實(shí)例的屬性賦值,都是用<property…/>元素
Spring容器中Bean的作用域
1. Spring容器的bean的作用域通過(guò)sope屬性指定
<bean id=”test” class=”com.dfsj.Test” scope=”prototype”>a) singleton:在IOC容器中只生成一個(gè)實(shí)例
b) prototype:每次通過(guò)容器的getBean()方法獲取該作用域的Bean時(shí),都將產(chǎn)生一個(gè)新的實(shí)例
a) reqeust:對(duì)于一次http請(qǐng)求,該作用域下的Bean只生成一個(gè)實(shí)例
b) session:對(duì)于一次會(huì)話,只生成一個(gè)實(shí)例
c) global session:在全局會(huì)話,里生成一個(gè)實(shí)例
5 注
在springMVC框架中,已有SpringDispatherServlet或DispatherServlet來(lái)攔截處理所有和請(qǐng)求有關(guān)的狀態(tài)處理,所以不需要如編號(hào)4的Listerner配置。
6. 這里的bean的作用域具體指的是什么?
如果一個(gè)bean的scope屬性設(shè)置為singleton,則表示在整個(gè)IOC容器內(nèi),在注入到其他對(duì)象中時(shí),只要唯一確定是該bean(可通過(guò)id確定),則都會(huì)是同一個(gè)bean,而不是去重新new一個(gè)新的bean對(duì)象。
如果一個(gè)bean的scope屬性設(shè)置為prototype,則表示在注入到其他對(duì)象中或用getBean方法得到時(shí),雖然指向的是同一個(gè)bean,但都會(huì)重新new一個(gè)新的對(duì)象。
Spring核心機(jī)制:依賴注入
1.注入方式
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)的順序?yàn)闇?zhǔn),除非以index屬性指定(下標(biāo)從0開(kāi)始)3.在使用spring框架時(shí),眼睛看到xml配置時(shí),心中要想到底層Java代碼是如何實(shí)現(xiàn)的,用得熟練時(shí),看到任何一段Java代碼都能用xml文件配置也來(lái)
2 各種注入示例
2.注入基本數(shù)據(jù)類(lèi)型
<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個(gè)屬性:
key:當(dāng)key值是基本數(shù)據(jù)類(lèi)型或字符串類(lèi)型時(shí)使用
key-ref:當(dāng)key值是引用類(lèi)型時(shí)使用
value:當(dāng)value值是基本數(shù)據(jù)或字符串類(lèi)型時(shí)使用
value-ref:當(dāng)value值是引用類(lèi)型時(shí)使用
示例:給private Map<String,Axe> axes注入
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類(lèi)實(shí)現(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注(因?yàn)榉盒?#xff0c;所以可以注入各種類(lèi)型的)
<bean id="test" class="com.test.Test">< property name=”set” > <set>< value>普通字符串< value/> //基本數(shù)據(jù)類(lèi)型或字符串<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í),如果這些集合未泛型,則其值可以是基本數(shù)據(jù)類(lèi)型、字符串、容器中其他Bean、嵌套Bean、集合等各種數(shù)據(jù)類(lèi)型,如上面Set集合注入的示例
Spring的組合屬性
1. 所謂組合屬性,就是一個(gè)類(lèi)的屬性還有自己的屬性。因?yàn)樯婕暗秸{(diào)用,所以在使用組合屬性時(shí),除最后一個(gè)屬性外,前面調(diào)用者都不能為空。
2. 示例
3.Spring中的Bean與Java的Bean的區(qū)別
傳統(tǒng)的JavaBean作為對(duì)象,要求每個(gè)屬性都必須提供getter setter方法,而SpringBean只需要為接受設(shè)值注入的屬性提供setter方法即可,但是如果要獲取該屬性值,還是需要寫(xiě)getter方法的
傳統(tǒng)的JavaBean不接受容器的管理,而SpringBean是由spring容器管理它的生命周期和行為的
Spring的Java配置管理
Spring的Java配置管理,代替了之前的xml文件配置管理
1. 實(shí)現(xiàn)
1)利用**@Configuration注解修飾的類(lèi)(后面就叫配置類(lèi))代替xml文件
2)有@Bean**注解修飾一個(gè)方法,該方法的返回的對(duì)象將定義成容器中的Bean
3)用@Value注解修飾一個(gè)Field,相當(dāng)于配置一個(gè)變量
2. 示例
3.Java配置管理時(shí)創(chuàng)建容器
ApplicationContext app = new AnnotationConfigApplicationContext(AppConfig.class);如果是web應(yīng)用,則用AnnotationConfigWebApplicationContext創(chuàng)建
4.XML配置管理與Java配置管理的混用
1)在xml配置文件中導(dǎo)入Java配置類(lèi)
2)在Java配置類(lèi)里導(dǎo)入xml配置文件
@Configuration @ImportResource("classpath:/beans.xml") public class AppConfig{ //…. }5.Java配置類(lèi)的其他注解
1)@Import:修飾Java類(lèi),用于導(dǎo)入其他Java配置類(lèi)
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>從上面示例中可以看到,并沒(méi)有用class屬性指定類(lèi),這是為什么呢?
因?yàn)槲覀冎?#xff0c;抽象Bean是不可被實(shí)例化的,即便指了類(lèi)的完整名也不會(huì)用到,還有就是,Spring中的Bean的繼承是對(duì)象與對(duì)象之間的關(guān)系,而不是類(lèi)與類(lèi)之間的關(guān)系,只存在參數(shù)之間的傳遞,所以抽象類(lèi)須指定參數(shù)。抽象類(lèi)的屬性值,在子類(lèi)當(dāng)中也能獲取到。
2. 繼承Bean
1)在Spring中,Bean的繼承是由parent屬性指定的,如:
<bean id="son" class="com.dfsj.Son" parent="test"> parent指定的值是父類(lèi)在容器中的id2)當(dāng)子類(lèi)信息與父類(lèi)信息不一致時(shí),子類(lèi)的覆蓋父類(lèi)的
3)子類(lèi)無(wú)法從父類(lèi)繼承這些屬性:depends-on、autowire、singleton、scope、lazy-init
3 .Spring中Bean的繼承與Java中類(lèi)的繼承的區(qū)別:
1)前者是對(duì)象與對(duì)象之間的關(guān)系,后者是類(lèi)與類(lèi)的關(guān)系
2)前者主要表現(xiàn)為參數(shù)值的延續(xù),后者主要是方法、屬性的延續(xù)
3)Spring中的Bean不可作為父Bean使用,而Java中子類(lèi)可以當(dāng)成父類(lèi)實(shí)例使用
4.工廠Bean
詳情參見(jiàn)P580-P582
1.工廠Bean是實(shí)現(xiàn)FactoryBean接口的Bean
2.FactoryBean接口提供了如下幾個(gè)方法:
(1) T getObject():返回該工廠的自定義內(nèi)容
(2) class<?> getObjectType():返回該工廠自定義內(nèi)容(java實(shí)例)的類(lèi)型(實(shí)現(xiàn)類(lèi))
(3) boolean isSingleton():返回自定義的java實(shí)例是否為單例模式
3.工廠Bean配置在xml文件后,通過(guò)Spring容器的getBean()方法獲取時(shí),得到的不是該Bean的實(shí)例,而是由開(kāi)發(fā)者在getOject()方法里自定義的返回值,可能是一個(gè)數(shù)字,也可能是一個(gè)字符串,也可能是一個(gè)對(duì)象,所以此時(shí)配置工廠Bean時(shí)的id屬性指定的是getObject方法返回值在容器中的唯一標(biāo)識(shí)。
4.如何返回工廠Bean本身?
當(dāng)我們?cè)谟肧pring容器的getBean()方法獲取工廠Bean時(shí),在id前面加上"&"符
號(hào)即可,如:
5.強(qiáng)制初始化其他Bean
如果某個(gè)類(lèi)的初始化塊中使用了其他Bean,則這種依賴不夠直接,當(dāng)spring初始主調(diào)Bean時(shí),可能會(huì)由于初始化塊中的其他Bean還未被初始化,則會(huì)拋出像空指針之類(lèi)的異常。這時(shí)我們可通過(guò)depends-on屬性在初始化主調(diào)Bean前強(qiáng)制先初始化其他Bean,如:
Spring中Bean的生命周期
1. prototype作用域的Bean的生命周期
當(dāng)Spring容器創(chuàng)建了prototype作用域的Bean實(shí)例之后,Bean實(shí)例完全交給客戶端代碼管理,容器不再跟蹤其生命周期,且每次客戶端請(qǐng)求該Bean時(shí),都會(huì)新建一個(gè)實(shí)例。
2. singleton作用域的Bean的生命周期
每次客戶端請(qǐng)深圳市singleton作用域的Bean時(shí),返回的都是同一個(gè)實(shí)例,spring容器負(fù)責(zé)跟蹤Bean實(shí)例的產(chǎn)生和銷(xiāo)毀。
3. Spring如何管理Bean的生命周期
1)依賴注入之后的行為,兩種方式:
(1) 通過(guò)實(shí)現(xiàn)InitializingBean接口,然后利用afterPropertiesSet()方法處理
(2) 通過(guò)<bean.../>元素的init-method屬性指定的方法處理
2)Bean銷(xiāo)毀之前的行為,兩種方式
(1) 通過(guò)實(shí)現(xiàn)DisposableBean接口,然后利用destroy()方法處理
(2) 通過(guò)<bean.../>元素的destroy-method屬性指定要執(zhí)行的處理方法
如果(1)、(2)兩種方式都實(shí)現(xiàn)了,則在依賴注入之后,先執(zhí)行(1)的方法
Spring的其他依賴配置
如果Spring框架用得熟練,別人給你任何一段Java代碼,你都能用spring的配置文件配置出來(lái)。前面了解了用<property.../>元素配setter方法、用<constructor-arg.../>元素配置有參構(gòu)造等等,下面我們來(lái)了解下如何配一個(gè)類(lèi)的setter方法、普通方法、屬性、Field
詳情參見(jiàn)P592~P599
1. 使用PropertyPathFactoryBean獲取其他Bean的屬性值
1)PropertyPathFactoryBean屬于工廠Bean,所以獲得其他Bean的屬性值的原理就是利用工廠Bean的getObject自定義返回值實(shí)現(xiàn)的,示例如:
<bean id="test" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"><!-- person是Person類(lèi)在容器中的id --><property name="targetBeanName" value="person"/> <property name="propertyPath" value="name"/> </bean>2)解釋上面配置:給PropertyPathFactoryBean的targetBeanName屬性注入指定Bean的id,給propertyPath屬性注入指定需要返回值的屬性,通過(guò)容器獲的getBean(“test”)方法獲取的值就是Person類(lèi)的name屬性的值
3)獲取指定Bean的具體某個(gè)屬性值的簡(jiǎn)單方式:
<bean id="son.age" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>//此時(shí)容器getBean方法得這樣寫(xiě):getBean("son.age"); //son是Son類(lèi)在容器中的唯一標(biāo)識(shí)2. 使用FieldRetrivingFactoryBean獲取其他Bean的Field值
首先要明確的是,這里所說(shuō)的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)獲取實(shí)例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="傳一個(gè)參數(shù)" /> </bean>Spring基于xml Schema的簡(jiǎn)化配置
1. p:命名空間
p:命名空間用于代替<property.../>元素進(jìn)行設(shè)值注入
1.語(yǔ)法
1)基本數(shù)據(jù)類(lèi)型屬性:p:屬性名=“值”
2)引用類(lèi)型屬性:p:屬性名-ref=“引用Bean的id”
2.導(dǎo)入p:命名空間
3.示例
<bean id="test" class="com.dfsj.Test" p:name="peter" p:person-ref="person"/> //等價(jià)于: <bean id="test" class=" com.dfsj.Test "><property name="name" value="peter"/ ><property name="person" ref="person"/ > </bean>如果Bean的屬性名以"-ref" 結(jié)尾,那么采用p:命名空間就會(huì)發(fā)生沖突
2. c:命名空間
c:命名空間用于代替<constructorg-arg.../>元素
1. 導(dǎo)入c:命名空間
http://www.springframework.org/schema/c
2. 語(yǔ)法
index是參數(shù)下標(biāo),從0開(kāi)始
1)基本數(shù)據(jù)類(lèi)型:c:構(gòu)造參數(shù)名=“值” 或c:_index=“值”
2)引用類(lèi)型:c: 構(gòu)造參數(shù)名-ref=“引用Bean的id” 或 c:_index-ref=“其他Bean的id”
3.示例
3. util命名空間
1.constant
用于獲取指定類(lèi)的靜態(tài)Field值,它是FieldRetrievingFactoryBean的簡(jiǎn)化配置,如:
2.property-path
用于獲取指定對(duì)象的getter方法的返回值,它是PropertyPathFactoryBean的簡(jiǎn)化,如:
用于定義一個(gè)List集合,支持<value.../>、<ref.../>、<bean.../>等子元素,如:
4.set
用于定義一個(gè)Set集合,支持<value.../>、<ref.../>、<bean.../>等元素,如:
5.map
用于定義一個(gè)Set集合,支持<entry.../>元素定義key-value對(duì),如:
6.properties
用于加載一份資源文件,并創(chuàng)建一個(gè)Properties實(shí)例
4.Spring的其他簡(jiǎn)化配置的schema
spring的兩種后處理器
Bean后處理器:對(duì)容器中的Bean進(jìn)行后處理,進(jìn)行額外的加強(qiáng)
容器后處理器:對(duì)IOC容器進(jìn)行后處理,用于增強(qiáng)容器的功能
后處理器英文:Post Processor
1. Bean后處理器
定義
實(shí)現(xiàn)BeanPostProcessor接口的Bean就是Bean后處理器,它可對(duì)容器中的某一批Bean進(jìn)行增強(qiáng)處理
BeanPostProcessor接口有如下兩個(gè)方法:
下同的bean是要處理的Bean實(shí)例,name是該Bean配置的id
1)Object postProcessBeforeInitialization(Object bean, String name) throws Exception
在注入依賴之后初始化Bean之前調(diào)用
如果指定了init-method屬性,則在它指定的方法之后執(zhí)行
兩個(gè)常見(jiàn)的Bean后處理器
1)BeanNameAutoProxyCreator:根據(jù)實(shí)例Bean的name屬性創(chuàng)建Bean實(shí)例的代理
2)DefaultAdvisorAutoProxyCreator:根據(jù)提供的Advisor對(duì)容器中的所有Bean他建代理
Bean后處理器會(huì)對(duì)容器中的所有Bean進(jìn)行后處理(在方法里可過(guò)濾掉某些不需要處理的Bean),所以在配置Bean后處理器可以不用指定id。如果用BeanFactroy作為Spring容器,則程序必須先獲取Bean后處理器實(shí)例,然后手動(dòng)注冊(cè),詳情參見(jiàn)P617
Bean后處理器與其他初始化方法的執(zhí)行順序
注入完成
Bean后處理器的postProcessBeforeInitialization方法
InitializingBean接口的afterPropertiesSet方法
init-method屬性指定的方法
Bean后處理器的postProcessAfterInitialization方法
2. 容器后處理器
實(shí)現(xiàn)BeanFactoryPostProcessor接口的類(lèi)就是容器后處理器,它負(fù)處理容器本身
void postProcessBeanFactory(ConfigurableListableBeanFactory bean) throws BeansException;
1)PropertyPlaceholderConfigurer:屬性占位符配置器
2)PropertyOverrideConfigurer:重寫(xiě)占位符配置器
3)CustomAutowireConfigurer:自定義自動(dòng)裝配的配置器
4)CustomScopeConfigurer:自定義作用域的配置器
3.容器后處理器之屬性占位符配置器
username=“Peter”
password=“123456”
4.基于XML Schema的簡(jiǎn)化配置
<context:property-placeholder location="classpath:myPropertyFile.properties"/>4.容器后處理器之重寫(xiě)占位符配置器
容器中配置的Bean的id.該Bean的屬性 = 值
3.基于XML Schema的簡(jiǎn)化配置
<context:property-override location="classpath:myPropertyFile.properties"/>Spring 注解之零配置
1.指定SpringBean的注解
@Component :標(biāo)注Java類(lèi)為普通Spring Bean
@Controller :標(biāo)注Java類(lèi)為控制器組件
@Service :標(biāo)注Java類(lèi)為業(yè)務(wù)邏輯組件
@Repository :標(biāo)注Java類(lèi)為DAO組件
默認(rèn)spring bean的名字是對(duì)應(yīng)Java類(lèi)的類(lèi)名小寫(xiě)首字母
自定義名字,如: @Component(“myName”)
2.搜索Spring Bean
滿足<include-filter.../>規(guī)則的Java類(lèi)會(huì)被當(dāng)成Spring Bean
滿足< exclude-filter.../>規(guī)則的Java類(lèi)不會(huì)被當(dāng)成Spring Bean
上面兩元素都要求指定如下兩屬性:
type:指定過(guò)濾器類(lèi)型,有4種類(lèi)型:
annotation:此時(shí)表達(dá)式需要指定一個(gè)Annotation類(lèi)完整名
assignable:此時(shí)表達(dá)式需要指定一個(gè)Java類(lèi)
regex:此時(shí)表達(dá)式需要指定.一個(gè)正則表達(dá)式
aspectj:此時(shí)表達(dá)式需要指定一個(gè)AspectJ過(guò)濾器,如:org.example…*Service+
expression:指定過(guò)濾器需要的表達(dá)式
示例:
3.配置依賴的@Resource注解
4.指定Bean作用域的@Scope注解
Spring Bean的默認(rèn)作用域是singleton
定義Spring Bean作用域,如:
@Scope("prototype")@Component("user")public class User { ...}自定義作用域解析器(不再基于Annotation的方法來(lái)指定作用域)
自定義解析器類(lèi)必須實(shí)現(xiàn)ScopeMetadataResolver接口,還要配置在< component-scan.../>元素中,如:
5 定制SpringBean生命周期行為的注解
@PostConstruct、@PreDestroy都直接來(lái)源于JavaEE規(guī)范,都用于修飾方法
@PostConstruct修飾的方法在完成注入之后回調(diào),如果被它修飾的類(lèi)實(shí)現(xiàn)了InitializingBean接口,則@PostConstruct修飾的方法在afterPropertiesSet方法之前執(zhí)行
@PreDestroy 修飾的方法在Bean銷(xiāo)毀前回調(diào)執(zhí)行
6 自動(dòng)裝配和精裝配的注解
7 Spring的其他注解
@DependsOn({“chinese”,“japanese”}) //在初化Person類(lèi)前初化chinese、japanese
@ DependsOn(“chinese”) //只強(qiáng)制初始化一個(gè)Bean
@Lazy(true) :表示要延遲初始化該Bean,即不預(yù)初始化。
Spring的AOP
為什么需要AOP?
面向?qū)ο缶幊?#xff08;OOP)里,如果有共用的代碼我們一般的做法是提取出一個(gè)公共方法供大家調(diào)用,這種方式并沒(méi)有完全解耦,比如說(shuō)有一個(gè)方法之前調(diào)用過(guò)公共代碼,現(xiàn)需求變成該方法不需要調(diào)用公共代碼了,此時(shí)我們還得去該方法里刪除公共代碼塊。
而面向切面編程(AOP)不止能提取出公共代碼,而且還能控制哪些方法調(diào)用該公共代碼,其他方法根本不知道發(fā)生了什么變化,這就實(shí)現(xiàn)了完全的解耦。所有AOP很有用。
比如事務(wù)管理、安全檢查、緩存、對(duì)象池管理等等都是很好的AOP思想。
spring的AOP也需要jar包:aspectjweaver.jar和aspectjtr.jar
在Spring的AOP中,連接點(diǎn)(切入點(diǎn))總是方法的調(diào)用
1 基于注解管理的AOP
1.1 使用步驟
在spring配置文件中加入下面配置:
2.定義切面Bean
定義切面Bean用@Aspect注解,如:
定義好的切面Bean也需要掃描成Spring Bean,有如下兩種方式:
1):在切面Bean里加入@Component注解
2):用include-filter元素:
3.定義一個(gè)要被增強(qiáng)處理的類(lèi)
@Component public class User {public void say(){System.out.println("被增強(qiáng)處理的方法");} }4.指定切入點(diǎn)和增強(qiáng)處理方法
@Aspect @Component public class BeforeAop {//訪問(wèn)修飾符public 可省略@Before("execution(public void com.User.User.say())")public void before(){System.out.println("在之前切入點(diǎn)之前的增強(qiáng)處理");} }execution方法是用來(lái)指定切入點(diǎn)的,這和AspectJ的語(yǔ)法一樣。
由于通常的增強(qiáng)處理是對(duì)一批方法的處理,所以需要通匹配符*,如下:
根據(jù)Before Aop里的示例可知,第一個(gè)*表示返回值為任意類(lèi)型,第二個(gè)*表示所有類(lèi),第三個(gè)*表示所有方法,括號(hào)里的…表示任意參數(shù)
如果是某個(gè)包及其子包的所有類(lèi)的所有方法都要匹配,則應(yīng)如下:
…代表零個(gè)或多個(gè)
1.2 簡(jiǎn)單示例
執(zhí)行結(jié)果:
在切入點(diǎn)之前的增強(qiáng)處理
被增強(qiáng)處理的方法
1.3 定義After增強(qiáng)處理
2.After增強(qiáng)處理與AfterReturning 增強(qiáng)處理的區(qū)別:
After增強(qiáng)處理不論目標(biāo)方法是否正常結(jié)束,都會(huì)調(diào)用處理
AfterReturning 只在目標(biāo)方法成功完成后才處理調(diào)用
1.4 定義AfterReturning 增強(qiáng)處理
pointcut/value:這兩屬性作用一樣,用于指定切入點(diǎn)的表達(dá)式
returning:指定一個(gè)返回值形參名,該增強(qiáng)處理定義的方法可通過(guò)該形參名來(lái)訪問(wèn)目標(biāo)方法的返回值
還有一屬性argNames:參數(shù)列表參數(shù)名
1.5 定義AfterThrowing增強(qiáng)處理
類(lèi)似于AfterReturning增強(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)方法什么時(shí)候執(zhí)行。如:
ProceedingJoinPoint是JointPoint的子類(lèi),其他增強(qiáng)處理的方法里如要想獲得傳入?yún)?shù)就得通過(guò)JointPoint的getArgs方法。
注:只有Around增強(qiáng)處理能改變目標(biāo)方法參數(shù)。
1.7 相同增強(qiáng)處理執(zhí)行順序
1、如果是同一個(gè)切面類(lèi)里有兩個(gè)相同的增強(qiáng)處理在同一個(gè)連接點(diǎn)被織入時(shí),Spring Aop將隨機(jī)織入這兩個(gè)增強(qiáng)處理。
2、 如果是兩個(gè)切面類(lèi)里有相同的增強(qiáng)處理在同一個(gè)連接點(diǎn)被織入時(shí),具有高優(yōu)先級(jí)的增強(qiáng)處理將先被織入。
3、指定優(yōu)先級(jí)的兩個(gè)方法:
1)讓切面類(lèi)實(shí)現(xiàn)org.springframework.core.Ordered接口,然后實(shí)現(xiàn)int getOrder()方法,該方法的返回值越小,優(yōu)先級(jí)越高
2)用@Order注解修飾切面類(lèi),此時(shí)可指定一個(gè)int型的value,值越小優(yōu)先級(jí)越高
1.8定義切入點(diǎn)
AspectdJ和Spring都允許定義切入點(diǎn),即為一個(gè)切入點(diǎn)表達(dá)式起一個(gè)名字,從而允許在多個(gè)增強(qiáng)處理中能重復(fù)調(diào)用。
1、定義:用@Pointcut注解修飾一個(gè)返回類(lèi)型為void的空方法,方法名即為切入點(diǎn)名字。
如果希望該切入點(diǎn)只能在本切面類(lèi)使用,則需將public改為private
2、引用:
1) 在同一個(gè)切面類(lèi)里可直接引用,如:
2) 如果是引用不同切面類(lèi)里的切入點(diǎn),則需要加上其他切面類(lèi)的類(lèi)名,如:
@After(value="OtherAdvice.myPointcut()") public void after(){System.out.println("after......"); }1.9 切入點(diǎn)指示符
execution(訪問(wèn)修飾符 目標(biāo)方法返回值類(lèi)型 目標(biāo)所屬類(lèi).目標(biāo)方法名(形參列表)目標(biāo)拋出異常)
execution(public * * (…)) //匹配任意public方法
execution(* set*(…)) //匹配任何方法名以set開(kāi)始的方法
execution(* com.aop.User.(…)) //匹配User類(lèi)的所有方法
execution( com..(…)) //匹配一個(gè)包中任意類(lèi)的任意方法
within(com.aop.) //匹配aop包中的任意方法
within(com.aop…) //匹配aop包及其子包的任意方法
this(com.aop.UserInter) //匹配AOP實(shí)現(xiàn)UserInter接口,注意是AOP,不太理解
4.target:匹配目標(biāo)對(duì)象必須是指定類(lèi)型
target(com.aop.User)
args(java.lang.String) //只匹配傳入?yún)?shù)是String類(lèi)型,且只傳一個(gè)參數(shù)的所有目標(biāo)方法
這與execution(* *(java.lang.String))不同,execution里表示只匹配只包含一個(gè)String類(lèi)型形參的方法
6.bean:只匹配指定Bean實(shí)例的目標(biāo)方法
bean(*Service) // 匹配名字以Service結(jié)尾的bean實(shí)例
其中名字是Bean的id或name
1.10 切入點(diǎn)組合表達(dá)式
&&:同時(shí)匹配
||:只需要滿足一個(gè)切入點(diǎn)表達(dá)式即可
!:匹配不是該切入點(diǎn)表達(dá)式的其他連接點(diǎn)
示例:
只要不是User類(lèi)的目標(biāo)方法都能被匹配
2基于xml配置的AOP
不推薦使用XML配置方式,推薦使用@Aspect
2.1 注意
1、基于注解的AOP配置能被Spring AOP和AspectJ同時(shí)支持
2、使用 <aop:config…/>元素可能與Spring的自動(dòng)代理方式?jīng)_突,因此,要么全部使用<aop:config…/>配置方式,要么全部使用自動(dòng)代理方式,不能二者混用
3、XML配置方式僅支持”singleton”的切面Bean,不能在xml中組合多個(gè)命名連接點(diǎn)的聲明
4、XML配置方式時(shí),所有關(guān)于AOP的信息都必須配在<aop:config…/>元素中
5、如果<aop:config…/>元素里同時(shí)有<aop:pointcut…/>、<aop:advisor…/>、<aop:aspect…/>元素時(shí),必須是pointcut、advisor、aspect這樣的出現(xiàn)順序。
6、如果是要增強(qiáng)處理一個(gè)有返回值的目標(biāo)方法,則對(duì)應(yīng)切面類(lèi)的增強(qiáng)方法也必須寫(xiě)上返回值,否則系統(tǒng)一直處于等待狀態(tài)中。
7、XML方式的組合運(yùn)算符:and(相當(dāng)于&&)、or(相當(dāng)于||)、not(相當(dāng)于!)
8、遺留問(wèn)題:<aop:advisor…/>是什么?跟spring自動(dòng)代理有什么關(guān)系?什么是自動(dòng)代理?
2.2 示例與說(shuō)明
1、切面類(lèi):
注:當(dāng)<aop:pointcut…/>元素是<aop:aspect >的子元素時(shí),說(shuō)明該切入點(diǎn)只能被當(dāng)前切面類(lèi)使用
Spring的事務(wù)
1. Spring支持的事務(wù)策略
spring各種全局事務(wù)、局部事務(wù)示例配置,參見(jiàn)P683-P685
1.1 全局事務(wù)
###1.2 局部事務(wù)
1.3 PlatformTransactionManager
isNewTransaction():判斷是否是一個(gè)新事務(wù)
setRollbackOnly():設(shè)置回滾
isRollbackOnly():判斷是否有回滾標(biāo)志
2 Spring的兩種事務(wù)管理方式
2.1 編程式配置事務(wù)
2.2 聲明式配置事務(wù)
3.注意:
spring支持接口代理,也支持對(duì)具體的類(lèi)生成代理。
如果一個(gè)具體的實(shí)現(xiàn)類(lèi)如UserDaoImpl沒(méi)有實(shí)現(xiàn)接口,按如下配置沒(méi)有問(wèn)題;但是,如果UserDaoImpl類(lèi)實(shí)現(xiàn)了接口,則下面的配置將會(huì)報(bào)錯(cuò),要解決這個(gè)問(wèn)題,需要在配置文件中設(shè)置proxy-target-class屬性的值為true,如下:
這是因?yàn)?#xff0c;Spring默認(rèn)采用JDK動(dòng)態(tài)代理,而CGLIB代理是面向接口代理的,二者區(qū)別需查閱相關(guān)資料。
2.3 示例:
對(duì)應(yīng)配置文件:
對(duì)應(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í)行下面的非讀操作會(huì)報(bào)錯(cuò)//jt.update("insert into workers_info values(id,workername) values(1,你好)");} }spring還可以為不同的方法指定不同的事務(wù)策略,具體參見(jiàn)P691
spring還允許將事務(wù)放在Java類(lèi)中定義(@Transaction注解),具體參見(jiàn)P692
3 spring事務(wù)的傳播屬性
Spring補(bǔ)充知識(shí)
ApplicationContextAware
參考:https://www.jianshu.com/p/4c0723615a52
注解@ControllerAdvice
POJO:簡(jiǎn)單的Java對(duì)象即JavaBean
EJB:服務(wù)器端組件模型
本人將知識(shí)都生成了圖片,地址:https://img-blog.csdn.net/20160930173240547
總結(jié)
以上是生活随笔為你收集整理的spring知识概要的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring创建Bean的3种方式
- 下一篇: springMVC的@RequestPa