AOP底層原理解析
阿新 • • 發佈:2019-01-27
1 什麼是AOP:
AOP AspectOrientedPrograming面向切面程式設計
AOP採取橫向抽取機制,取代了傳統縱向繼承體系重複性程式碼(效能監視、事務管理、安全檢查、快取)
Spring AOP使用純Java實現,不需要專門的編譯過程和類載入器,在執行期通過代理方式向目標類織入增強程式碼
AspecJ是一個基於Java語言的AOP框架,Spring2.0開始,Spring AOP引入對Aspect的支援,
AspectJ擴充套件了Java語言,提供了一個專門的編譯器,在編譯時提供橫向程式碼的織入
2 AOP底層原理;
就是代理機制:
*動態代理:(JDK中使用)
- * JDK
- * JDK
3 Spring的AOP代理:
JDK動態代理:對實現了介面的類生成代理
CGLib代理機制:對類生成代理
4 AOP的術語:
Joinpoint(連線點):所謂連線點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支援方法型別的連線點.
Pointcut(切入點):所謂切入點是指我們要對哪些Joinpoint進行攔截的定義.
Advice(通知/增強):所謂通知是指攔截到Joinpoint之後所要做的事情就是通知.通知分為前置通知,後置通知,異常通知,最終通知,環繞通知(切面要完成的功能)
Introduction
Target(目標物件):代理的目標物件
Weaving(織入):是指把增強應用到目標物件來建立新的代理物件的過程.
Proxy(代理):一個類被AOP織入增強後,就產生一個結果代理類
Aspect(切面):是切入點和通知(引介)的結合
spring採用動態代理織入,而AspectJ採用編譯期織入和類裝在期織入
對於不使用介面的業務類,無法使用JDK動態代理
CGlib採用非常底層位元組碼技術,可以為一個類建立子類,解決無介面代理問題
5 AOP的底層實現 :
5.1 JDK動態代理
JDK1.3引入動態代理技術
編寫動態代理程式
java.lang.reflect.Proxy
java.lang.reflect.InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Title: JDK的動態代理的機制
* @ClassName:JDKProxy.java
* @Description:
*
* @Copyright 2016-2017 Powered By 研發中心
* @author: 王延飛
* @date:2016年9月19日 下午10:28:08
* @version V1.0
*/
publicclassJDKProxyimplementsInvocationHandler[]{
privateUserDao userDao;
publicJDKProxy(UserDao userDao){
super();
this.userDao = userDao;
}
publicUserDao createProxy(){
UserDao proxy =(UserDao)Proxy.newProxyInstance(userDao.getClass()
.getClassLoader(), userDao.getClass().getInterfaces(),this);
return proxy;
}
// 呼叫目標物件的任何一個方法 都相當於呼叫invoke();
publicObject invoke(Object proxy,Method method,Object[] args)
throwsThrowable{
if("add".equals(method.getName())){
// 記錄日誌:
System.out.println("日誌記錄=================");
Object result = method.invoke(userDao, args);
return result;
}
return method.invoke(userDao, args);
}
}
5.2 CGLIB動態代理
對於不使用介面的業務類,無法使用JDK動態代理
CGlib採用非常底層位元組碼技術,可以為一個類建立子類,解決無介面代理問題
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* 使用CGLib生成代理物件
*
*/
publicclassCGLibProxyimplementsMethodInterceptor{
privateProductDao productDao;
publicCGLibProxy(ProductDao productDao){
super();
this.productDao = productDao;
}
publicProductDao createProxy(){
// 使用CGLIB生成代理:
// 1.建立核心類:
Enhancer enhancer =newEnhancer();
// 2.為其設定父類:
enhancer.setSuperclass(productDao.getClass());
// 3.設定回撥:(相當於JDK動態代理中的回撥)
enhancer.setCallback(this);
// 4.建立代理:
return(ProductDao) enhancer.create();
}
- /** * @param proxy CGlib根據指定父類生成的代理物件 * @param method 攔截的方法 * @param args 攔截方法的引數陣列 * @param methodProxy 方法的代理物件,用於執行父類的方法 * @return */
publicObject intercept(Object proxy,Method method,Object[] args,
MethodProxy methodProxy)throwsThrowable{
if("add".equals(method.getName())){
System.out.println("日誌記錄==============");
// 放行程式碼:這裡相當於JDK中的(method.invoke)
Object obj = methodProxy.invokeSuper(proxy, args);
return obj;
}
return methodProxy.invokeSuper(proxy, args);
}
}
5.3 代理總結
Spring在執行期,生成動態代理物件,不需要特殊的編譯器
Spring AOP的底層就是通過JDK動態代理或CGLib動態代理技術為目標Bean執行橫向織入
- 1.若目標物件實現了若干介面,spring使用JDK的java.lang.reflect.Proxy類代理。
- 2.若目標物件沒有實現任何介面,spring使用CGLIB庫生成目標物件的子類。
程式中應優先對介面建立代理,便於程式解耦維護
標記為final的方法,不能被代理,因為無法進行覆蓋
- JDK動態代理,是針對介面生成子類,介面中方法不能使用final修飾
- CGLib是針對目標類生產子類,因此類或方法不能使final的
Spring只支援方法連線點,不提供屬性連線