大同网站建设熊掌号,自己做的网站本地虚拟上传,搜索动图素材的网站,wordpress 评论框文章目录 #x1f343;前言#x1f340;Spring AOP源码剖析⭕总结 #x1f343;前言
前面的博客中#xff0c;博主对代理模式进行了一个简单的讲解#xff0c;接下来博主将对Spring AOP源码进行简单剖析#xff0c;使我们对Spring AOP了解的更加深刻。
#x1f340;Sp… 文章目录 前言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 )* 即使我们配置了proxyTargetClassfalse, 经过这⾥的⼀些判断还是可能会将其设为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-classfalse 来进⾏修改,设置默认为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-classtrue cglib代理, 运⾏成功* 设置spring.aop.proxy-target-classfalse 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源码简单剖析》就讲解到这儿感谢大家的支持欢迎各位留言交流以及批评指正如果文章对您有帮助或者觉得作者写的还不错可以点一下关注点赞收藏支持一下