4种实例 advice aop_《Spring实战》阅读笔记
簡化 Java 開發(fā)
為了降低 Java 開發(fā)的復雜性, Spring 采取了以下 4 種關鍵策略:基于POJO (Plain Old Java object) 的輕量級和最小侵入性編程
通過依賴注入和面向接口實現(xiàn)松耦合
基于切面和慣例進行聲明式編程
通過切面和模板減少樣板式代碼
依賴注入 (DI)
傳統(tǒng)做法下,每個對象負責管理與自己所依賴的對象的引用,這樣會導致高耦合。
通過依賴注入,對象的依賴關系將由一個第三方組件在創(chuàng)建對象時進行自動注入,對象無需管理它們的依賴關系。
依賴注入的實現(xiàn)方式:構造器注入:在構造方法中將依賴對象作為參數(shù)傳入
XML
注解
Spring 通過 Application Context 裝載 bean 的定義并負責對象的創(chuàng)建與組裝。
面向切面編程 (AOP)
AOP 允許將遍布應用各處的重復功能,分離出來形成可重用的組件。
Spring 提供了 4 種類型的 AOP 支持:基于代理的經(jīng)典 Spring AOP
純 POJO切 面
@AspectJ 注解驅動的切面
注入式 AspectJ 切面(適用于 Spring 各版本)
Weaving (織入)
織入是把切面應用到目標對象并創(chuàng)建新的代理對象的過程。在目標對象的生命周期里有多個點
可以進行織入:編譯期:切面在目標類編譯時被織入。這種方式需要特殊的編譯器。AspectJ的織入編譯器就是以這種方式織入切面的。
類加載期:切面在目標類加載到JVM時被織入。這種方式需要特殊的類加載器(ClassLoader),它可以在目標類被引入應用之前增強該目標類的字節(jié)碼。AspectJ 5的加載時織入(load-time
weaving,LTW)就支持以這種方式織入切面。
運行期:切面在應用運行的某個時刻被織入。一般情況下,在織入切面時,AOP容器會為目標對象動態(tài)地創(chuàng)建一個代理對象。Spring AOP就是以這種方式織入切面的。
Aspect (切面)
切面是 Advice 和 Pointcut 的結合。通知和切點共同定義了切面的全部內容——它是什么,在何時和何處完成其功能。
Advice (通知)
即切面的具體工作,Advice定義了切面是什么以及何時使用。除了描述切面要完成的工作,
通知還解決了何時執(zhí)行這個工作的問題。
Spring 中的 AOP 定義了以下5種 Advice:前置通知(Before):在目標方法被調用之前調用通知功能
后置通知(After):在目標方法完成之后調用通知,此時不會關心方法的輸出是什么
返回通知(After-returning):在目標方法成功執(zhí)行之后調用通知
異常通知(After-throwing):在目標方法拋出異常后調用通知
環(huán)繞通知(Around):通知包裹了被通知的方法,在被通知的方法調用之前和調用之后執(zhí)行自定義的行為
Joint point (連接點)
連接點是在應用執(zhí)行過程中能夠插入切面的一個點。
這個點可以是調用方法時、拋出異常時、甚至修改一個字段時。切面代碼可以利用這些點插入到應用的正常流程之中,并添加新的行為。
Spring 只支持方法級別的 Joint point。
Pointcut (切點)
如果說 Advice 定義了切面的“什么”和“何時”的話,那么 Pointcut 就定義了“何處”。
切點的定義會匹配通知所要織入的一個或多個 Joint point。通常使用明確的類和方法名稱,或是利用正則表達式定義所匹配的類和方法名稱來指定這些切點。
有些 AOP 框架還允許創(chuàng)建動態(tài)的切點。
Spring 容器
Spring 容器負責創(chuàng)建、裝配與配置對象,并管理對象的整個生命周期(從 new 到 finalize( ))。
Spring 自帶了不同類型的容器實現(xiàn);Bean工廠,是最簡單的容器,提供基本DI支持。
應用上下文 (Application Context),基于BeanFactory構建,提供面向應用的服務,例如,解析屬性文本信息內容。
Application Context
Spring 自帶了多種 Application Context 的實現(xiàn),區(qū)別僅在于如何加載配置。AnnotationConfigApplicationContext:從一個或多個基于 Java 的配置類中加載 Spring 應用上下文。
ClassPathXmlApplicationContext:從一個或多個基于 Java 的配置類中加載 Spring Web 應用上下文。
FileSystemXmlApplicationContext:從類路徑下的一個或多個 XML 配置文件中加載上下文定義,把應用上下文的定義文件作為類資源。
XmlWebApplicationContext:從 Web 應用下的一個或多個 XML 配置文件中加載上下文定義。
Bean 的生命周期
Spring對bean進行實例化;
Spring將值和bean的引用注入到bean對應的屬性中;
如果bean實現(xiàn)了BeanNameAware接口,Spring將bean的ID傳遞給setBean-Name()方法;
如果bean實現(xiàn)了BeanFactoryAware接口,Spring將調用setBeanFactory()方法,將BeanFactory容器實例傳入;
如果bean實現(xiàn)了ApplicationContextAware接口,Spring將調用setApplicationContext()方法,將bean所在的應用上下文的引用傳入進來;
如果bean實現(xiàn)了BeanPostProcessor接口,Spring將調用它們的post-ProcessBeforeInitialization()方法;
如果bean實現(xiàn)了InitializingBean接口,Spring將調用它們的after-PropertiesSet()方法。類似地,如果bean使用initmethod聲明了初始化方法,該方法也會被調用;
如果bean實現(xiàn)了BeanPostProcessor接口,Spring將調用它們的post-ProcessAfterInitialization()方法;
此時,bean已經(jīng)準備就緒,可以被應用程序使用了,它們將一直駐留在應用上下文中,直到該應用上下文被銷毀;
10.如果bean實現(xiàn)了DisposableBean接口,Spring將調用它的destroy()接口方法。同樣,如果bean使用destroy-method聲明了銷毀方法,該方法也會被調用。
Spring 中的 Bean
Spring 中提供了三種主要的裝配機制:在XML中進行顯式配置。
在Java中進行顯式配置。
隱式的 bean 發(fā)現(xiàn)機制和自動裝配
其中自動裝配是通過以下兩種方式來實現(xiàn)的:組件掃描(component scanning):Spring會自動發(fā)現(xiàn)應用上下文
中所創(chuàng)建的bean。
自動裝配(autowiring):Spring自動滿足bean之間的依賴。
聲明 Bean
使用@Component注解,解表明該類會作為組件類,并告知Spring要為這個類創(chuàng)建 bean。
然后使用@ComponentScan注解開啟組件掃描,默認情況下它將以配置類所在的package作為base package來掃描組件。
消除 Autowired 的歧義性
通過 @Primary 配置首選自動裝配的 bean 或通過 @Qualifier 來限定自動裝配的 bean。
Bean 的作用域
默認情況下,Spring ApplicationContext 中所有 bean 都是作為單例的形式創(chuàng)建的。
通過 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 注解可以設置其他的作用域,或者是@Scope('prototype'),但是用 SCOPE_PROTOTYPE 常量更加安全不易出錯。
Spring 定義了多種作用域,可以基于這些作用域創(chuàng)建 bean,包括:單例(Singleton):在整個應用中,只創(chuàng)建 bean 的一個實例。
原型(Prototype):每次注入或者通過 Spring ApplicationContext 獲取的時候,都會創(chuàng)建一個新的 bean 實例。
會話(Session):在 Web 應用中,為每個會話創(chuàng)建一個 bean 實例。
請求(Request):在 Web 應用中,為每個請求創(chuàng)建一個 bean 實例。
會話作用域與請求作用域
設想一個電商場景中的一個 bean 代表用戶的購物車,如果這個 bean 是單例的,那么所有用戶都會向同個購物車中添加商品,如果是原型的,在應用中某個地方添加了商品,在另一個地方可能就拿不到了。在這個場景下,會話作用域是最為合適的。
使用會話作用域:1
2
3
4
5
6
7@Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.INTERFACES)
public ShoppingCart (){
...
}
注意一點,@Scope注解同時還有一個proxyMode屬性,這個屬性解決了將會話或請求作用域的bean注入到單例bean中所遇到的問題。
如果將一個會話作用域的bean注入到一個單例bean中,只有某個用戶發(fā)起會員,這個單例bean才會被注入依賴的會話作用域bean。當注入時,Spring 并不會將實際的會話作用域bean注入到單例bean中,而是注入到單例bean的代理,如下圖所示。
這個代理會暴露與會話作用域bean相同的方法,當單例bean調用會話作用域bean的方法時,代理會對其進行懶解析并將調用委托給對應的會話作用域bean。
上面的proxyMode屬性被設置成了ScopedProxyMode.INTERFACES,這表明這個代理要實現(xiàn)接口,并將調用委托給實現(xiàn)bean。如果對應的bean不是接口而是類的話,則需要設置為ScopedProxyMode.TARGET_CLASS。
總結
以上是生活随笔為你收集整理的4种实例 advice aop_《Spring实战》阅读笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity 通用透明物体漫反射Shade
- 下一篇: java oauth server_Sp