0


【JavaEE进阶】 Spring AOP源码简单剖析

文章目录

🍃前言

前面的博客中,博主对代理模式进行了一个简单的讲解,接下来博主将对Spring AOP源码进行简单剖析,使我们对Spring AOP了解的更加深刻。

🍀Spring AOP源码剖析

Spring AOP 主要基于两种⽅式实现的:JDK 及 CGLIB 的⽅式

Spring对于AOP的实现,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成⽣成代理对象的逻辑在⽗类 AbstractAutoProxyCreator 中

相关源码与注解如下:

protectedObjectcreateProxy(Class<?> beanClass,@NullableString beanName,@NullableObject[] specificInterceptors,TargetSource targetSource){if(this.beanFactory instanceofConfigurableListableBeanFactory){AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);}//创建代理⼯⼚ProxyFactory proxyFactory =newProxyFactory();
    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 instanceofSmartClassLoader&& 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进⾏装配
@SpringBootApplicationpublicclassDemoApplication{publicstaticvoidmain(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)

我们再看以下代理⼯⼚的代码

publicclassProxyFactoryextendsProxyCreatorSupport{//...代码省略//获取代理publicObjectgetProxy(@NullableClassLoader classLoader){//分两步 先createAopProxy,后getProxyreturncreateAopProxy().getProxy(classLoader);}protectedfinalsynchronizedAopProxycreateAopProxy(){if(!this.active){activate();}returngetAopProxyFactory().createAopProxy(this);}//...代码省略}

createAopProxy的实现在DefaultAopProxyFactory中

publicclassDefaultAopProxyFactoryimplementsAopProxyFactory,Serializable{//...代码省略@OverridepublicAopProxycreateAopProxy(AdvisedSupport config)throwsAopConfigException{/**
 * 根据proxyTargetClass判断
 * 如果⽬标类是接⼝, 使⽤JDK动态代理
 * 否则使⽤cglib动态代理
 */if(!NativeDetector.inNativeImage()&&(config.isOptimize()|| config.isProxyTargetClass()||hasNoUserSuppliedProxyInterfaces(config))){Class<?> targetClass = config.getTargetClass();if(targetClass ==null){thrownewAopConfigException("TargetSource cannot determine
                        target class: " +
                "Either an interface or a target is required for proxy
                creation.");}if(targetClass.isInterface()||Proxy.isProxyClass(targetClass)||ClassUtils.isLambdaClass(targetClass)){returnnewJdkDynamicAopProxy(config);}returnnewObjenesisCglibAopProxy(config);}else{returnnewJdkDynamicAopProxy(config);}}//...代码省略}

接下来就是创建代理了

JDK动态代理

finalclassJdkDynamicAopProxyimplementsAopProxy,InvocationHandler,Serializable{//...代码省略@OverridepublicObjectgetProxy(@NullableClassLoader classLoader){if(logger.isTraceEnabled()){
            logger.trace("Creating JDK dynamic proxy: "+this.advised.getTargetSource());}returnProxy.newProxyInstance(determineClassLoader(classLoader),this.proxiedInterfaces,this);}//...代码省略}

CGLIB动态代理

classCglibAopProxyimplementsAopProxy,Serializable{//...代码省略@OverridepublicObjectgetProxy(@NullableClassLoader classLoader){//...代码省略// Configure CGLIB Enhancer...Enhancer enhancer =createEnhancer();// Generate the proxy class and create a proxy instance.returncreateProxyClassAndInstance(enhancer, callbacks);}//...代码省略}

以上就是对Spring AOP源码的一个简单剖析。

⭕总结

关于《【JavaEE进阶】 Spring AOP源码简单剖析》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下

标签: java-ee spring java

本文转载自: https://blog.csdn.net/m0_71731682/article/details/136417589
版权归原作者 遇事问春风乄 所有, 如有侵权,请联系我们删除。

“【JavaEE进阶】 Spring AOP源码简单剖析”的评论:

还没有评论