【Spring AOP】AOP 底層實現原理 —— 動態代理類的建立(JDK、CGlib)、工廠如何加工原始物件
AOP 程式設計
AOP 概念
POP (Producer Oriented Programing)
- 程式導向(方法、函式)程式設計 —— C
- 以過程為基本單位的程式開發,通過過程間的彼此協同,相互呼叫,完成程式的構建。
OOP (Object Oritened Programing)
- 物件導向程式設計 —— Java
- 以物件為基本單位的程式開發,通過物件間的彼此協同,相互呼叫,完成程式的構建。
AOP (Aspect Oriented Programing)
- 面向切面程式設計 = Spring動態代理開發
- 以切面為基本單位的程式開發,通過切面間的彼此協同,相互呼叫,完成程式的構建。
- 切面 = 切入點 + 額外功能
AOP 的概念:
- 本質就是 Spring 的動態代理開發,通過代理類為原始類增加額外功能。
- 好處:利於原始類的維護
- 注意:AOP 程式設計不可能取代 OOP,AOP 是 OOP 程式設計的補充。
AOP 程式設計的開發步驟
- 原始物件
- 額外功能 (
MethodInterceptor
) - 切入點
- 組裝切面 (額外功能+切入點)
詳情可參見之前的部落格:Spring 動態代理開發詳解
切面的名詞解釋
切面 = 切入點 + 額外功能
幾何學:面 = 點 + 相同的性質
AOP 的底層實現原理
核心問題:
- AOP 如何建立動態代理類?
動態位元組碼技術 - Spring 工廠如何加工建立代理物件?
通過原始物件的 id 值,獲得的是代理物件
動態代理類的建立
JDK 的動態代理(原理 + 編碼)
Proxy.newPorxyInstance
方法引數詳解- 編碼
public class TestJDKProxy {
/**
1. 借⽤類載入器 TestJDKProxy 或 UserServiceImpl 都可以
2. JDK8.x 前必須加 final
final UserService userService = new UserServiceImpl();
*/
public static void main(String[] args) {
// 1. 建立原始物件
UserService userService = new UserServiceImpl();
// 2. JDK 動態代理
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---- proxy log ----");
// 原始方法執行
Object ret = method.invoke(userService, args);
return ret;
}
};
UserService userServiceProxy = (UserService) Proxy.
newProxyInstance(TestJDKProxy.class.getClassLoader(),
userService.getClass().getInterfaces(),
handler);
userServiceProxy.login("zhenyu", "123456");
userServiceProxy.register(new User());
}
}
CGlib 的動態代理
CGlib 建立動態代理的原理:通過父子繼承關係建立代理物件,原始類作為父類,代理類作為子類,這樣既可以保證 2 者方法⼀致,同時在代理類中可以提供新的實現(額外功能+原始方法)。
- CGlib 編碼
public class TestCglib {
public static void main(String[] args) {
// 1. 建立原始物件
UserService userService = new UserService();
/*
2. 通過 cglib 方式建立動態代理物件
對比 jdk 動態代理 ---> Proxy.newProxyInstance(classLoader, interface, invocationHandler);
Enhancer.setClassLoader()
Enhancer.setSuperClass()
Enhancer.setCallBack() ---> MethodInterceptor(cglib)
Enhancer.createProxy() ---> 建立代理物件
*/
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(TestCglib.class.getClassLoader());
enhancer.setSuperclass(userService.getClass());
MethodInterceptor interceptor = new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("--- cglib log ----");
Object ret = method.invoke(userService, args); // 執行原始方法
return ret;
}
};
enhancer.setCallback(interceptor);
UserService userServiceProxy = (UserService) enhancer.create();
userServiceProxy.login("zhenyu", "123456");
userServiceProxy.register(new User());
}
}
總結
- JDK 動態代理
Proxy.newProxyInstance
:通過介面建立代理的實現類 - Cglib 動態代理
Enhancer
:通過繼承⽗類建立的代理類
Spring 工廠如何加工原始物件
- 思路分析:主要通過
BeanPostProcessor
將原始物件加工為代理物件
- 編碼
public class ProxyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("--- new log ---");
Object ret = method.invoke(bean, args);
return ret;
}
};
return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), handler);
}
}
<bean id="userService" class="com.yusael.factory.UserServiceImpl"/>
<!--1. 實現 BeanPostProcessor 進行加工-->
<!--2. 配置檔案中對 BeanPostProcessor 進行配置-->
<bean id="proxyBeanPostProcessor" class="com.yusael.factory.ProxyBeanPostProcessor"/>
相關文章
- spring aop原理 JDK動態代理和CGLIB動態代理SpringJDKCGLib
- AOP底層原理之CGlibCGLib
- 15-Spring AOP的底層實現原理JDKProxy&CGLIBSpringJDKCGLib
- Java JDK 動態代理(AOP)使用及實現原理分析JavaJDK
- Spring AOP --JDK動態代理方式SpringJDK
- Java-JDK動態代理(AOP)使用及實現原理分析JavaJDK
- 淺析Spring中AOP的實現原理——動態代理Spring
- Spring原始碼-AOP(六)-AOP代理的建立Spring原始碼
- Spring AOP概述、底層實現Spring
- Spring框架系列(10) - Spring AOP實現原理詳解之AOP代理的建立Spring框架
- 死磕Spring之AOP篇 - Spring AOP自動代理(三)建立代理物件Spring物件
- 死磕Spring之AOP篇 - 初識JDK、CGLIB兩種動態代理SpringJDKCGLib
- 【Spring】AOP的代理預設是Jdk還是Cglib?SpringJDKCGLib
- Spring框架系列(11) - Spring AOP實現原理詳解之Cglib代理實現Spring框架CGLib
- Spring AOP 實現原理與 CGLIB 應用SpringCGLib
- 菜鳥學SSH(十四)——Spring容器AOP的實現原理——動態代理Spring
- Spring AOP 自動建立代理Spring
- Spring框架系列(12) - Spring AOP實現原理詳解之JDK代理實現Spring框架JDK
- Spring原始碼剖析5:JDK和cglib動態代理原理詳解Spring原始碼JDKCGLib
- Spring AOP的實現原理Spring
- Spring的JDK動態代理如何實現的(原始碼解析)SpringJDK原始碼
- 【Spring】AOP實現原理Spring
- Spring AOP實現原理Spring
- CGLib動態代理原理及實現CGLib
- AOP - 自己寫 JDK 動態代理增強 beanJDKBean
- 簡單實現類似Spring的Aop原理實現Spring
- AOP詳解之三-建立AOP代理後記,建立AOP代理
- 深入理解Spring AOP的動態代理Spring
- 從動態代理到Spring AOP(上)Spring
- 從動態代理到Spring AOP(中)Spring
- Java動態代理(AOP)Java
- AOP之動態代理
- Spring動態代理的生成-如何判斷是使用JDK動態代理還是CGlib代理SpringJDKCGLib
- 動態代理jdk的Proxy與spring的CGlibJDKSpringCGLib
- JDK動態代理和 CGLIB 代理JDKCGLib
- JDK動態代理和CGLib代理JDKCGLib
- Java動態代理 jdk和cglib的實現比較JavaJDKCGLib
- JDK 和 CGLib 實現動態代理和區別JDKCGLib