關於Spring AOP與IOC的個人思考
在閱讀本文前,強烈建議閱讀一下(有分析,有demo):
Java JDK 動態代理(AOP)使用及實現原理分析
AOP是Spring提供的關鍵特性之一。AOP即面向切面程式設計,是OOP程式設計的有效補充。使用AOP技術,可以將一些系統性相關的程式設計工作,獨立提取出來,獨立實現,然後通過切面切入進系統。從而避免了在業務邏輯的程式碼中混入很多的系統相關的邏輯——比如許可權管理,事物管理,日誌記錄等等。這些系統性的程式設計工作都可以獨立編碼實現,然後通過AOP技術切入進系統即可。從而達到了將不同的關注點分離出來的效果。本文深入剖析Spring的AOP的原理。
一、AOP相關的概念
1)Aspect:切面,切入系統的一個切面。比如事務管理是一個切面,許可權管理也是一個切面;
2)Join point:連線點,也就是可以進行橫向切入的位置;
3)Advice:通知,切面在某個連線點執行的操作(分為:Before advice,After returning advice,After throwing advice,After (finally) advice,Around advice);
4)Pointcut:切點,符合切點表示式的連線點,也就是真正被切入的地方;
這一部分的應用可以參考:
Spring MVC AOP通過註解方式攔截Controller等實現日誌管理
二、AOP 的實現原理
AOP分為靜態AOP和動態AOP。靜態AOP是指AspectJ實現的AOP,他是將切面程式碼直接編譯到Java類檔案中。動態AOP是指將切面程式碼進行動態織入實現的AOP。Spring的AOP為動態AOP,實現的技術為:JDK提供的動態代理技術 和 CGLIB(動態位元組碼增強技術)。儘管實現技術不一樣,但都是基於代理模式,都是生成一個代理物件。
1、JDK動態代理
JDK部分解析參考:
2、CGLIB(code generate libary)
位元組碼生成技術實現AOP,其實就是繼承被代理物件,然後Override需要被代理的方法,在覆蓋該方法時,自然是可以插入我們自己的程式碼的。
因為需要Override被代理物件的方法,所以自然CGLIB技術實現AOP時,就必須要求需要被代理的方法不能是final方法,因為final方法不能被子類覆蓋。
package net.aazj.aop;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGProxy implements MethodInterceptor{
private Object target; // 被代理物件
public CGProxy(Object target){
this.target = target;
}
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.println("do sth before....");
Object result = proxy.invokeSuper(arg0, arg2);
System.out.println("do sth after....");
return result;
}
public Object getProxyObject() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass()); // 設定父類
// 設定回撥
enhancer.setCallback(this); // 在呼叫父類方法時,回撥 this.intercept()
// 建立代理物件
return enhancer.create();
}
}
public class CGProxyTest {
public static void main(String[] args){
Object proxyedObject = new UserServiceImpl(); // 被代理的物件
CGProxy cgProxy = new CGProxy(proxyedObject);
UserService proxyObject = (UserService) cgProxy.getProxyObject();
proxyObject.getUser(1);
proxyObject.addUser(new User());
}
}
輸出結果:
do sth before....
getUser from database.
do sth after....
do sth before....
add user into database.
do sth after....
它的原理是生成一個父類enhancer.setSuperclass(this.target.getClass())的子類enhancer.create(),然後對父類的方法進行攔截enhancer.setCallback(this). 對父類的方法進行覆蓋,所以父類方法不能是final的。
三、思考
從以上兩種代理方式可以看出,實現AOP的關鍵是:動態代理,即將需要用的介面、類再包裝一層,通過動態修改位元組碼檔案實現各種攔截與通知。
注意,兩者都需要:要代理真實物件的例項。
比如: 在Spring MVC的Controller層一般@Autowired是Service介面,但帶有@Service標識的卻是實現Service介面的實體類,這樣對於JDK動態代理來說已經足以生成代理類了(其實,不過是cglib還是jdk的動態代理,你直接@Autowired Service介面實現類,也是可以注入成功的,但不如注入Service介面靈活),大家在跟蹤程式碼的時候可以看一下Spring注入的bean真正的型別,你就可以發現它是代理生成的例項。
比如這種:
帶有註解標識的介面或者在Spring.XML中配置的bean會在Spring初始化的時候,被Spring通過反射載入例項化到Spring容器中,寫過CS模式的朋友應該知道,在Application執行過程中一般都會有一個應用上下文Context,將一些系統資訊放在裡面,比如一些登入資訊、WCF連線例項等。這些資訊在系統的任何地方都可以取到(其實就是一些頂級變數集合,生命週期最長的一些傢伙)。
換個角度想一下,如果我們在Application初始化的時候,用反射(獲取要代理物件的例項)和動態代理獲取有註解標識或者在xml中配置bean的例項,並放到應用上下文Context中,在需要的地方都能取到,這不就是一個簡單版的Spring 容器嗎?
生命週期的資料可以參考:
.Net 垃圾回收和大物件處理
深入理解JVM讀書筆記二: 垃圾收集器與記憶體分配策略
本文開頭及CGLIB部分參考:Spring AOP 深入剖析
作者:jiankunking 出處:http://blog.csdn.net/jiankunking
個人微信公眾號:
相關文章
- Spring AOP IOCSpring
- 對於Spring中AOP,DI,IoC概念的理解Spring
- spring ioc和aopSpring
- 對Spring IOC容器的思考Spring
- Spring Boot之IOC&AOPSpring Boot
- spring入門aop和iocSpring
- 如何理解Spring中的IOC和AOPSpring
- 最詳細的spring(IOC、AOP)教程Spring
- 仿寫一個簡陋的 IOC/AOP 框架 mini-spring框架Spring
- Spring關於IOC思想的簡要理解Spring
- spring:spring再總結(ioc、aop、DI等)Spring
- Java開發必讀,談談對Spring IOC與AOP的理解JavaSpring
- BeanPostProcessor——連線Spring IOC和AOP的橋樑BeanSpring
- 關於Dapper實現讀寫分離的個人思考APP
- 個人成長中,關於規劃設計的思考
- ioc aop
- IOC,AOP
- Spring IOC/AOP原理極簡概念入門Spring
- 關於Spring Aop和事務記錄Spring
- spring 詳細講解(ioc,依賴注入,aop)Spring依賴注入
- spring5原始碼-ioc抽象層次設計 與 aop流程理解Spring原始碼抽象
- 理解Spring(一):Spring 與 IoCSpring
- 關於我對Spring迴圈依賴的思考Spring
- 關於PHP協程與阻塞的思考PHP
- Spring學習筆記2(IOC註解方式&AOP)Spring筆記
- 深入淺出解讀 Spring 原始碼:IOC/AOP 篇Spring原始碼
- 關於orm的個人測試——SqlSugar與FreeSqlORMSqlSugar
- Spring基於註解的IoC配置Spring
- Spring框架學習筆記(一):官方文件介紹,IoC與AOP概念學習Spring框架筆記
- 談談對IOC及DI的理解與思考
- Spring基於註解的aop配置Spring
- 關於performSelector:afterDelay:的一個坑及思考performSelector
- 關於GAN的個人理解
- Spring學習01--初學者關於AOP和DI的理解Spring
- Java關於空指標的防範與思考Java指標
- golang中關於死鎖的思考與學習Golang
- Spring-boot整合AOP及AOP相關學習Springboot
- 關於搭建遊戲平臺的四個思考遊戲
- Spring中基於XML方式的AOP操作SpringXML