一文搞定AOP

        AOP,一个老生长谈的话题。在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等,本文不会对AOP的使用,配置做过多讲解,而是直接深入源码底层,看Spring中的AOP是怎么实现的。

        你在平时开发中有没有出现过配置了事物回滚不管用,配置了log的切面不打印的情况?看完这篇文章希望能帮你彻底了解AOP的底层机制,知道怎么正确的使用AOP。

        本文开始之前,先铺垫几个概念,方便下文的阐述,如果想更深入了解这些概念,可以关注我后边的文章。

        BeanDefinition:bean的定义信息,主要用来描述一个bean,spring中的类是先变为bd后变为对象,我们可以通过修改bd的属性来干预对象的创建;

         ImportBeanDefinitionRegistrar :spring的扩展点之一,可以用来向工厂中放入BeanDefinition,从而在工厂创建bean的时候可以创建你加入的bean;

          BeanPostProcessor:bean的后置处理器用来干预对象生成前后做一些你期望做的事情。

        基于注解的AOP使用时在配置类中引入了@EnableAspectJAutoProxy这个注解,点进去发现@EnableAspectJAutoProxy注解上有这行代码@Import(AspectJAutoProxyRegistrar.class),代表我在refresh时后也会将AspectJAutoProxyRegistrar这个类转换为bd放入到BeanDefinitionMap中,作为原料,从而在后边创建这个对象。那这个类实际就是AOP实现的核心类的入口,下图是这个类的继承关系。

AspectJAutoProxyRegistrar继承关系

                  从上边代码可以看出,AspectJAutoProxyRegistrar实现了这个ImportBeanDefinitionRegistrar这个类,结合上边引入的概念,不难猜测此处是要向工厂的BeanDefinitionMap放入一个BeanDefinition,事实也正是我们所想的,可以看//1这个代码,跟进去发现此处是注册了AnnotationAwareAspectJAutoProxyCreator的bd。那我们再来看一看AnnotationAwareAspectJAutoProxyCreator这个类的继承关系


继承关系图

        AnnotationAwareAspectJAutoProxyCreator可以看到最终还是实现了BeanPostProcessor,这也就是说明,spring试图把这个类加入到bdMap中并且实力话以后,来干预其他bean的一个创建。此处暂时省略一些细节问题

        那使用过BeanPostProcessor这个类的都知道,其中有两个方法需要实现,暂时只关注bean创建完成后的方法需要执行的方法。org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization 这个为他抽象父类实现了方法。其中有行代码return wrapIfNecessary(bean, beanName, cacheKey);如果需要的话对bean对象进行包装。那怎么包装的呢,我们跟进去方法会看到如下实现

方法实现

        图中1这个位置,是获取所有的增强点,即你在配置aop中配置的包的路径,或者方法名称等,会根据配置检查当前的bean或者方法是不是匹配这个增强点,如果匹配,最终这个位置为返回。没有则为DO_NOT_PROXY,即不需要代理,具体的实现可以看代码,是循环遍历比对。那如果需要代理,则会传入到2所示的位置,运用动态代理技术创建代理对象,外部会把这个对象放入到bean工厂中。如果想看具体的细节,会发现方法里面就是判断是用jdk的代理还是cglib的代理创建对象。

        这段代码可以知道,满足我们AOP配置的类,即使类中只有一个方法也会对类进行代理,而且在bean工厂中存的是代理类而不是我们的普通类,那有人可能会问,那其他不需要的代理的方法怎么办,那我们可以进入到代理类的执行逻辑去查看。

        假设是用JDK动态代理,那看调用的话实际就是找JdkDynamicAopProxy 实现了InvocationHandler 在invoke方法中做了处理。

继承关系

        截取一小段代码,看一下怎么调用代理方法和调用不被代理的方法

invoke实现

        代码中可以看到是在调用方法的时候去判断当前的方法需不需要进行代理,如果代理链为空,那么则调用原方法,如果方法满足代理条件,在组成一个调用链,先执行代理方法,在执行实际方法。感兴趣的可以点开阅读怎么执行的代理链。

        好了到此位置,已经把AOP的源码讲完了,但是还有一点网了叙述,就是这个这个后置处理器的执行时间,我现在引入一下。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)  这个方法中 是做bean初始化前后的属性赋值或者执行一些我们需要执行的方法

        上边代码中可以看到是我们的bean创建完成之后,要执行BeanPostProcessor,然后在执行我说的代理的逻辑。

        好了,到此为止AOP源码实现已经解析完了,希望对大家有帮助,知道AOP的误区,那事物的执行逻辑也是类似的,就不展开讲了,最后在强调一下,如果要走代理,不必须是从bean工厂中拿出的创建好的代理的对象,通过执行代理方法来对我们本身的方法做增强。

        本文是建立在大家对bean工厂的实例化bean的实例化有了解的基础上,简化了那些的叙述,如果大家想要了解更多可以给我留言,并且以后也会继续更新spring相关的源码解析。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容