• Spring之AOP源码解析(中)


    前言

    在上一篇文章中,我们讲解了Spring中那些注解可能会产生AOP动态代理,我们通过源码发现,完成AOP相关操作都和ProxyFactory这个类有密切关系,这一篇我们将围绕这个类继续解析

    演示

    作用

    ProxyFactory采用策略模式生成动态代理对象,具体生成cglib动态代理还是jdk动态代理,是根据我们具体设置的内容所决定的,我们分别演示一下生成cglib动态代理和jdk动态代理两种情况。具体细节可以详细阅读DefaultAopProxyFactory的createAopProxy方法

    生成cglib动态代理

    1. package com.test.aop.test;
    2. public class CglibTarget {
    3. public void doObject() {
    4. System.out.println("CglibTarget doObject");
    5. }
    6. }
    1. package com.test.aop.test;
    2. import org.springframework.aop.framework.ProxyFactory;
    3. public class CglibProxy {
    4. public static void main(String[] args) {
    5. ProxyFactory proxyFactory = new ProxyFactory();
    6. proxyFactory.setTarget(new CglibTarget());
    7. CglibTarget proxy = (CglibTarget) proxyFactory.getProxy();
    8. proxy.doObject();
    9. }
    10. }

    我们可以发现最终是以cglib动态代理方式生成代理对象

     生成jdk动态代理

    1. package com.test.aop.test;
    2. public interface JdkTarget {
    3. void doObject();
    4. }
    1. package com.test.aop.test;
    2. public class JdkTargetImpl implements JdkTarget {
    3. @Override
    4. public void doObject() {
    5. System.out.println("JdkTargetImpl doObject");
    6. }
    7. }
    1. package com.test.aop.test;
    2. import org.springframework.aop.framework.ProxyFactory;
    3. import org.springframework.aop.target.SingletonTargetSource;
    4. public class JdkProxy {
    5. public static void main(String[] args) {
    6. ProxyFactory proxyFactory = new ProxyFactory();
    7. proxyFactory.setInterfaces(JdkTarget.class);
    8. proxyFactory.setTargetSource(new SingletonTargetSource(new JdkTargetImpl()));
    9. JdkTarget proxy = (JdkTarget) proxyFactory.getProxy();
    10. proxy.doObject();
    11. }
    12. }

    我们可以发现最终是以jdk动态代理方式生成代理对象 

    ProxyFactory源码解析

    我们先观察一下ProxyFactory这个类的继承关系

    我们以proxyFactory.getProxy()方法为切入口,进行源码解析 

    对上述流程进行梳理,见下图

    我们分别查看两种方式的代理过程

    jdk动态代理过程(JdkDynamicAopProxy)

    jdk动态代理的过程比较简单主要就是利用Proxy.newProxyInstance方法创建代理对象,会默认实现SpringProxy,Advised,DecoratingProxy三个接口

    cglib动态代理过程(CglibAopProxy) 

    cglib动态代理主要利用我们自定义的ProxyFactory对象,然后根据设置的参数构建Enhancer对象,然后创建代理对象。我们需要注意的是代理对象一共有七个拦截器,spring会根据我们调用的方法,指定拦截器。比如我们调用equal方法就会经过EqualsInterceptor拦截器,调用hashCode方法就会经过HashCodeInterceptor拦截器。我们主要需要关注的就是DynamicAdvisedInterceptor拦截器,除了equal、hashcode这些特殊的方法,普通方法一般都会经过这个拦截器。具体进入那个拦截器可以查看CglibAopProxy类的accept方法

    cglib动态代理的对象会默认实现SpringProxy,Advised两个接口

    ProxyFactory的重要属性Advisor

    我们在前文中说到@EnableTransactionManagement,@EnableAspectJAutoProxy完成AOP动态代理都是依靠AbstractAutoProxyCreator的postProcessAfterInitialization方法中完成的,其中最主要的方法是wrapIfNecessary,我们查看相关源码

    通过源码我们知道只有找到了,可以作用于当前bean的Advisor,spring才会进行动态代理

    我们在上文中提到了@EnableTransactionManagement,@EnableAspectJAutoProxy两个注解的渊源,然后得出结论:如果同时存在,最终只能存在一个优先级更高的BeanPostProcessor(bpp)

    那么@EnableAspectJAutoProxy这个注解注入了一个优先级更高的bpp,有什么扩展点呢?我们以上图中getAdvicesAndAdvisorsForBean方法为切入口进行分析

    @EnableTransactionManagement注入的bpp没有重写findCandidateAdvisors方法,其查找Advisor的方法为父类的默认实现。@EnableAspectJAutoProxy注解注入的bpp重写了findCandidateAdvisors方法,其在父类方法的基础上又试图通过BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors方法寻找更多的Advisor,最后再判断这些找到的Advisors是否可以作用在当前bean,如果存在可以作用于当前bean的Advisors,则进行AOP动态代理

     总结

    ProxyFactory这个类在Spring完成AOP动态代理的过程中起到了重要的作用,具体如下所述

    • 可以通过配置决定Spring进行aop动态代理的方式,比如将@EnableTransactionManagement注解的proxyTargetClass参数设置为true(不能保证一定进行cglib动态代理,具体可以查看DefaultAopProxyFactory的createAopProxy方法)
    • 可以设置监听器,监听动态代理对象
    • 可以决定是否提前暴露代理对象,比如将@EnableAspectJAutoProxy注解的exposeProxy参数设置为true,然后通过AopContext.currentProxy()就可以获取原始对象
    • 可以通过查找是否存在作用于指定bean的Advisors,来决定是否需要进行动态代理
  • 相关阅读:
    基于vue的教研室工作管理系统
    ImmunoChemistry艾美捷抗体涂层缓冲液解决方案
    Python批量替换文件中内容,效率加倍
    List<LinkedHashMap<String, String>>类型的数据转换为Map<String, List<String>>类型数据
    某ERP系统存在RCE漏洞
    基于51单片机智能晾衣架控制系统设计( proteus仿真+程序+设计报告+原理图+讲解视频)
    求点集中最近点对--期望线性法
    09链表-单链表移除元素
    【git】关于Git这一篇就够了
    Android开发之——Jetpack Compose基础(06)
  • 原文地址:https://blog.csdn.net/qq_38257958/article/details/136145220