一 IOC/DI
1 介紹
反轉(zhuǎn)資源獲取的方向. 傳統(tǒng)的資源查找方式要求組件向容器發(fā)起請求查找資源. 作為回應(yīng), 容器適時(shí)的返回資源. 而應(yīng)用了 IOC 之后, 則是容器主動(dòng)地將資源推送給它所管理的組件, 組件所要做的僅是選擇一種合適的方式來接受資源. 這種行為也被稱為查找的被動(dòng)形式
DI(Dependency Injection) — IOC 的一種實(shí)現(xiàn)手段:即組件以一些預(yù)先定義好的方式(例如: setter 方法)接受來自如容器的資源注入. 相對于 IOC 而言,這種表述更直接(容器向組件注入資源,方式有:屬性注入、構(gòu)造器注入
2 依賴注入的方式
- Autowired/resource 等等 (可以再屬性、構(gòu)造器、sertter上標(biāo)注)
- setter方法注入(xml中的利用property標(biāo)簽,實(shí)際是調(diào)用sertter方法)
- 構(gòu)造器注入
- 靜態(tài)/實(shí)例工廠(只找到xml里面的用法)
3 Spring容器
在 Spring IOC 容器讀取 Bean 配置創(chuàng)建 Bean 實(shí)例之前, 必須對它進(jìn)行實(shí)例化. 只有在容器實(shí)例化后, 才可以從 IOC 容器里獲取 Bean 實(shí)例并使用.
Spring 提供了兩種類型的 IOC 容器實(shí)現(xiàn).
- BeanFactory: IOC 容器的基本實(shí)現(xiàn).
- ApplicationContext: 提供了更多的高級(jí)特性. 是 BeanFactory 的子接口.
- BeanFactory 是 Spring 框架的基礎(chǔ)設(shè)施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的開發(fā)者,幾乎所有的應(yīng)用場合都**直接使用 ApplicationContext **而非底層的 BeanFactory。無論使用何種方式, 配置文件是相同的
4 IOC實(shí)現(xiàn)過程
參考:https://blog.csdn.net/q982151756/article/details/80291998
spring的IoC容器在實(shí)現(xiàn)控制反轉(zhuǎn)和依賴注入的過程中,可以劃分為兩個(gè)階段:
- 容器啟動(dòng)階段
-
Bean實(shí)例化階段
這兩個(gè)階段中,IoC容器分別作了以下這些事情:
先講BeanFactroy中的過程
1.容器啟動(dòng)階段
1.加載配置文件信息,封裝成BeanDefinition
2.處理所有的BeanFactoryPostProcessor(在對象創(chuàng)建前,可以修改對象定義)
2.Bean實(shí)例化階段
各種Aware接口
參考:https://blog.csdn.net/q982151756/article/details/80299547
總結(jié)幾點(diǎn):
1.容器是如何實(shí)現(xiàn)將Aware接口中規(guī)定的依賴注入到已經(jīng)生成的對象中的呢?
通過BeanPostProcessor.因?yàn)锽eanPostProcessor會(huì)處理所有的對象實(shí)例。所以在spring容器中實(shí)例化過程的某一步驟時(shí),容器會(huì)找到之前注冊到容器的ApplicationContextAwareProcessor這個(gè)BeanPostProcessor的實(shí)現(xiàn)類,然后就會(huì)調(diào)用其postProcessBeforeInitialization()方法,檢查并設(shè)置Aware相關(guān)依賴。
二 AOP
1 AOP中的相關(guān)概念
- Aspect(切面): Aspect 聲明類似于 Java 中的類聲明,在 Aspect 中會(huì)包含著一些 Pointcut 以及相應(yīng)的 Advice。
- Joint point(連接點(diǎn)):表示在程序中明確定義的點(diǎn),典型的包括方法調(diào)用,對類成員的訪問以及異常處理程序塊的執(zhí)行等等,它自身還可以嵌套其它 joint point。
- Pointcut(切點(diǎn)):表示一組 joint point,這些 joint point 或是通過邏輯關(guān)系組合起來,或是通過通配、正則表達(dá)式等方式集中起來,它定義了相應(yīng)的 Advice 將要發(fā)生的地方。
- Advice(增強(qiáng)):Advice 定義了在 Pointcut 里面定義的程序點(diǎn)具體要做的操作,它通過 before、after 和 around 來區(qū)別是在每個(gè) joint point 之前、之后還是代替執(zhí)行的代碼。
- Target(目標(biāo)對象):織入 Advice 的目標(biāo)對象.。
- Weaving(織入):將 Aspect 和其他對象連接起來, 并創(chuàng)建 Adviced object 的過程
詳見:
基本概念
point cut 用法等等
2 srping中的動(dòng)態(tài)代理
2.1 jdk動(dòng)態(tài)代理
通過創(chuàng)建接口的子類來實(shí)現(xiàn)的
詳見:https://blog.csdn.net/q982151756/article/details/80586894
2.2 cglib
CGLIB(基于ASM的字節(jié)碼生成庫)會(huì)動(dòng)態(tài)創(chuàng)建一個(gè)目標(biāo)類的子類,然后返回該子類的對象,也就是增強(qiáng)對象。
通過動(dòng)態(tài)字節(jié)碼技術(shù)實(shí)現(xiàn)的:動(dòng)態(tài)態(tài)字節(jié)碼技術(shù)就是通過轉(zhuǎn)換字節(jié)碼生成新的類來實(shí)現(xiàn)改變一個(gè)類的內(nèi)部邏輯的
基本用法參見:https://www.cnblogs.com/xrq730/p/6661692.html
總結(jié)
1.可以定義不同的攔截策略(通過CallbackFilter)
2.final方法不能被代理,Object的部分方法也會(huì)被代理
3.方法內(nèi)部調(diào)用也會(huì)被代理,全程代理(不同于jdk動(dòng)態(tài)代理)
4.spring aop中即使用了cglib,類中互相調(diào)用也不會(huì)被代理
3、4點(diǎn)原理
public class CarProxy implements MethodInterceptor {
private Object target;
CarProxy(Object target){
this.target = target;
}
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
System.out.println("Before Method Invoke");
//object是代理類(增強(qiáng)類,子類); method是父類的method; objects是參數(shù),沒什么好說的;proxy是代理類的method
// proxy.invokeSuper(object, objects);一般都是這么調(diào)的,所以全程一直被代理
// proxy.invoke(object,objects);//有異常
// System.out.println(object);
// System.out.println(method);
method.invoke(target,objects);//類似jdk動(dòng)態(tài)代理的實(shí)現(xiàn),spring aop使用cglib也類似這樣。這樣內(nèi)部方法互相調(diào)用就不會(huì)被代理
System.out.println("After Method Invoke");
return object;
}
}
原理參考: Cglib動(dòng)態(tài)代理實(shí)現(xiàn)原理
參考資料