文章目錄
- 🍃前言
- 🍀Spring AOP源碼剖析
- ?總結
🍃前言
前面的博客中,博主對代理模式進行了一個簡單的講解,接下來博主將對Spring AOP源碼進行簡單剖析,使我們對Spring AOP了解的更加深刻。
🍀Spring AOP源碼剖析
Spring AOP 主要基于兩種?式實現的:JDK 及 CGLIB 的?式
Spring對于AOP的實現,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成?成代理對象的邏輯在?類 AbstractAutoProxyCreator 中
相關源碼與注解如下:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);}
//創建代理??ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);
/*** 檢查proxyTargetClass屬性值,spring默認為false* proxyTargetClass 檢查接?是否對類代理, ?不是對接?代理* 如果代理對象為類, 設置為true, 使?cglib代理*/if (!proxyFactory.isProxyTargetClass()) {
//是否有設置cglib代理if (shouldProxyTargetClass(beanClass, beanName)) {
//設置proxyTargetClass為true,使?cglib代理proxyFactory.setProxyTargetClass(true);} else {
/*** 如果beanClass實現了接?,且接??少有?個?定義?法,則使?JDK代理* 否則CGLIB代理(設置ProxyTargetClass為true )* 即使我們配置了proxyTargetClass=false, 經過這?的?些判斷還是可能會將其設為true*/evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}
// Use original ClassLoader if bean class not locally loaded in overridingclass loader
ClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader && classLoader !=beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}
//從代理??中獲取代理return proxyFactory.getProxy(classLoader);
}
代理工?有?個重要的屬性:proxyTargetClass,默認值為false.
也可以通過程序設置
proxyTargetClass | ?標對象 | 代理?式 |
---|---|---|
false | 實現了接? | jdk代理 |
false | 未實現接?(只有實現類) | cglib代理 |
true | 實現了接? | cglib代理 |
true | 未實現接?(只有實現類) | cglib代理 |
可以通過 @EnableAspectJAutoProxy(proxyTargetClass = true) 來設置
需要注意的是:
- Spring Boot 2.X開始,默認使?CGLIB代理,可以通過配置項
spring.aop.proxy-target-class=false
來進?修改,設置默認為jdk代理
SpringBoot設置 @EnableAspectJAutoProxy ?效,因為Spring Boot默認使?AopAutoConfiguration進?裝配
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {ApplicationContext context =SpringApplication.run(DemoApplication.class, args);
/*** HouseProxy houseProxy = context.getBean(HouseProxy.class);* 設置spring.aop.proxy-target-class=true cglib代理, 運?成功* 設置spring.aop.proxy-target-class=false jdk代理, 運?失敗, 不能代理類* 因為 HouseProxy 是?個類, ?不是接?, 需要修改為* HouseSubject houseProxy = (HouseSubject)context.getBean("realHouseSubject")**/HouseProxy houseProxy = context.getBean(HouseProxy.class);
//HouseSubject houseProxy = (HouseSubject)context.getBean("realHouseSubject");//正確運?System.out.println(houseProxy.getClass().toString());}
}
注意:使?context.getBean()需要添加注解,使HouseProxy,RealHouseSubject被Spring管理測試AOP代理,需要把這些類交給AOP管理(?定義注解或使用@Aspect)
我們再看以下代理??的代碼
public class ProxyFactory extends ProxyCreatorSupport {//...代碼省略
//獲取代理public Object getProxy(@Nullable ClassLoader classLoader) {
//分兩步 先createAopProxy,后getProxyreturn createAopProxy().getProxy(classLoader);}protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}return getAopProxyFactory().createAopProxy(this);}
//...代碼省略
}
createAopProxy的實現在DefaultAopProxyFactory中
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {//...代碼省略@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throwsAopConfigException {
/*** 根據proxyTargetClass判斷* 如果?標類是接?, 使?JDK動態代理* 否則使?cglib動態代理*/if (!NativeDetector.inNativeImage() &&(config.isOptimize() || config.isProxyTargetClass() ||hasNoUserSuppliedProxyInterfaces(config))) {Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determinetarget class: " +"Either an interface or a target is required for proxycreation.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) ||ClassUtils.isLambdaClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
//...代碼省略
}
接下來就是創建代理了
JDK動態代理
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,Serializable {//...代碼省略@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " +this.advised.getTargetSource());}return Proxy.newProxyInstance(determineClassLoader(classLoader),this.proxiedInterfaces, this);}
//...代碼省略
}
CGLIB動態代理
class CglibAopProxy implements AopProxy, Serializable {//...代碼省略@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {//...代碼省略
// Configure CGLIB Enhancer...Enhancer enhancer = createEnhancer();
// Generate the proxy class and create a proxy instance.return createProxyClassAndInstance(enhancer, callbacks);}
//...代碼省略
}
以上就是對Spring AOP源碼的一個簡單剖析。
?總結
關于《【JavaEE進階】 Spring AOP源碼簡單剖析》就講解到這兒,感謝大家的支持,歡迎各位留言交流以及批評指正,如果文章對您有幫助或者覺得作者寫的還不錯可以點一下關注,點贊,收藏支持一下