文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring AOP底层源码详解

2024-04-02 19:55

关注

ProxyFactory的工作原理

ProxyFactory是一个代理对象生产工厂,在生成代理对象之前需要对代理工厂进行配置。ProxyFactory在生成代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术。


// config就是ProxyFactory对象
// optimize为true,或proxyTargetClass为true,或用户没有给ProxyFactory对象添加interface
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  Class<?> targetClass = config.getTargetClass();
  if (targetClass == null) {
    throw new AopConfigException("TargetSource cannot determine target class: " +
        "Either an interface or a target is required for proxy creation.");
  }
  // targetClass是接口,直接使用Jdk动态代理
  if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    return new JdkDynamicAopProxy(config);
  }
  // 使用Cglib
  return new ObjenesisCglibAopProxy(config);
}
else {
  // 使用Jdk动态代理
  return new JdkDynamicAopProxy(config);
}

JdkDynamicAopProxy创建代理对象过程

  1. 获取生成代理对象所需要实现的接口集合
  2. 获取通过ProxyFactory.addInterface()所添加的接口,如果没有通过ProxyFactory.addInterface()添加接口,那么则看ProxyFactory。setTargetClass()所设置的targetClass是不是一个接口,把接口添加到结果集合中,同时把SpringProxy、Advised、DecoratingProxy这几个接口也添加到结果集合中去。
  3. 确定好要代理的集合之后,就利用Proxy.newProxyInstance()生成一个代理对象。

JdkDynamicAopProxy创建代理对象执行过程

  1. 如果通过ProxyFactory.setExposeProxy()把exposeProxy设置为true,那么则把代理对象设置到一个ThreadLocal(currentProxy)中去。
  2. 获取通过ProxyFactory所设置的target,如果设置的是targetClass,那么target将为null
  3. 根据当前所调用的方法对象寻找ProxyFactory中所添加的并匹配的Advisor,并且把Advisor封装为MethodInterceptor返回,得到MethodIntercepter链叫做chain
  4. 如果chain为空,则字节执行target对应的当前方法,如果target为null会报错
  5. 如果chain不为空,则会依次执行chain中的MethodInterceptor。如果当前MethodInterceptor是MethodBeforeAdviceInterceptor,那么先执行Advisor中所advice的before()方法,然后执行下一个MethodInterceptor.如果当前MethodInterceptor是AfterReturningAdviceInterceptor,那么先执行执行下一个MethodInterceptor。拿到返回值后,再执行Advisor中所advice的afterReturning()方法

ObjenesisCglibAopProxy创建代理对象过程

  1. 创建Enhancer
  2. 设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类
  3. 设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advisor接口
  4. 设置Enhancer的Callbacks为DynamicAdvisedIntercepter
  5. 最后通过Enhancer创建一个代理对象

ObjenesisCglibAopProxy创建的代理对象执行过程

执行过程主要就看DynamicAdvisedInterceptor中的实现,执行逻辑和JdkDynamicAopProxy中是一样的。

自动代理(autoproxy)功能

“自动代理”表示只需要在Spring中添加某个Bean,这个Bean是一个BeanPostProcessor,那么Spring在每创建一个Bean时,都会经过这个BeanPost Processor的判断,去判断当前正在创建的这个Bean是不是需要进行AOP。

DefaultAdvisorAutoProxyCreator

AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,是一个BeanPostProcessor

  1. 在某个Bean实例化之前,查看该AbstractAutoProxyCreator中是不是设置了CustomTargetSource,如果设置了就查看当前Bean是不是需要创建一个TargetSource,如果需要就会创建一个TargetSource对象,然后进行AOP创建一个代理对象,并返回该代理对象
  2. 如果某个Bean出现了循环依赖,那么会利用getEarlyBeanReference()方法提前进行AOP
  3. 在某个Bean初始化之后,会调用wrapIfNecessary()方法进行AOP
  4. 在这个类中提供了一个抽象方法:getAdvicesAndAdvisorsForBean(),表示对于某个Bean匹配了哪些Advices和Advisors

AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator,AbstractAdvisorAutoProxyCreator中实现了getAdvicesAndAdvisorsForBean()方法,实现逻辑为:

  1. 调用findEligibleAdvisors()
  2. 调用findCandidateAdvisors,得到所有Advisor类型的Bean。按当前正在进行Bean的生命周期的Bean进行过滤

@EnableAspectJAutoProxy

这个注解主要是添加了一个AnnotationAwareAspectJAutoProxyCreator类型的BeanDefinition。AspectJAwareAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,重写了shouldSkip(Class<?> beanClass, String beanName)方法,表示某个bean需不需要进行AOP,在shouldSkip()方法中:

  1. 拿到所有的Advisor
  2. 遍历所有的Advisor,如果当前bean是AspectJPointcutAdvisor,那么则跳过

AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator,重写了findCandidateAdvisors()方法,它即可以找到Advisor类型的bean,也能把所有@Aspect注解标注的类扫描出来并生成Advisor

注解和源码对应关系

@Before对应的是AspectJMethodBeforeAdvice,直接实现MethodBeforeAdvice,在进行动态代理时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor,也就转变成了MethodBeforeAdviceInterceptor

  1. 先执行advice对应的方法
  2. 再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法

@After对应的是AspectJAfterAdvice,直接实现了MethodInterceptor

  1. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
  2. 再执行advice对应的方法

@Around对应的是AspectJAroundAdvice,直接实现了MethodInterceptor

直接执行advice对应的方法
@AfterThrowing对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor

  1. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
  2. 如果上面抛了Throwable,那么则会执行advice对应的方法

@AfterReturning对应的是AspectJAfterReturningAdvice,实现了AfterReturningAdvice,在进行动态代理时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor,也就转变成了MethodInterceptor

  1. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
  2. 执行上面的方法后得到最终的方法的返回值
  3. 再执行Advice对应的方法

以上就是Spring AOP底层源码详解的详细内容,更多关于Spring AOP底层源码的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯