登录后台

页面导航

本文编写于 758 天前,最后修改于 751 天前,其中某些信息可能已经过时。
  1. 从IOC容器中获取bean;
  2. 调用bean后置处理器AbstractAutoProxyCreatorpostProcessBeforeInstantiation()方法;
  3. 判断是否指定targetSource,如果指定了targetSource会跳过bean的实例化和初始化流程,也就是会直接创建AOP代理;
  4. 如果没有指定targetSource,执行正常创建bean的流程,执行bean的初始化,执行initMethod方法;
  5. 调用bean后置处理器AbstractAutoProxyCreatorpostProcessAfterInitialization()方法;
  6. 执行wrapIfNecessary方法包装需要被代理的bean;
  7. 获取所有的增强advisors

    1. 获取xml方式配置的增强advisors
    2. 获取@Aspect注解配置的增强advisors,调用BeanFactoryAspectJAdvisorsBuilderbuildAspectJAdvisors方法;
    3. 获取IOC容器中的所有bean,判断是否添加@Aspect注解;
    4. 添加了@Aspect注解的切面类,调用doWithMethods()方法遍历切面类的每个方法,找到其中标注了@Point@Around@Before@After@AfterReturning@AfterThrowing六种注解的方法;
    5. 找到标注了上面六种注解的方法后,构建一个AspectJExpressionPointcut切点对象,并设置注解中的切入点表达式;
    6. 通过增强方法candidateAdviceMethod和切点AspectJExpressionPointcut等信息通过InstantiationModelAwarePointcutAdvisorImpl的构造方法构建出一个Advisor
    7. 如果bean是单例就将<beanName,advisors>以键值对的形式缓存起来,如果bean不是单例,就将<beanName,factory>以键值对的形式缓存起来,方便下一次直接使用factory快速构建Advisors,并继续循环处理下一个bean;
  8. 调用findAdvisorsThatCanApply方法,从所有增强的advisor中找到与当前bean相匹配的增强Advisors
  9. 遍历当前bean中所有方法依次与advisor的切点表达式进行匹配;

    1. 如果是advisorIntroductionAdvisor引介增强的实现类,那么就进行类级别进行匹配(不常用);
    2. 默认的InstantiationModelAwarePointcutAdvisorImpl实现的是普通增强PointcutAdvisor接口,使用切点Pointcut进行方法级别的匹配;
    3. 先使用切点表达式和目标类进行匹配,确保类级别满足切点表达式;
    4. 遍历当前bean中的所有方法,使用aspectj提供的方法(SignaturePattern#matchesExactlyMethod),依次对切点表达式对方法进行精确匹配;

      1. 判断方法参数是否匹配;
      2. 判断方法名称是否匹配;
      3. 判断方法抛出异常是否匹配;
      4. 判断方法返回值是否匹配;
    5. 将所有匹配的Advisors使用Order接口进行排序并返回;
  10. 创建ProxyFactory对象,并设置相关属性;

    1. AnnotationAwareAspectJAutoProxyCreator复制proxyTargetClassoptimizeexposeProxyfrozenopaque等属性;
    2. 判断是基于类代理还是接口代理,也就是cglib代理还是jdk代理;

      1. 判断beanDefinition中是否定义了preserveTargetClass属性,如果配置为true就将proxyTargetClass设置为true,表示使用cglib进行类代理;
      2. 判断目标类是否有如何要求的接口,如有符合要求的接口,就将接口添加到proxyFatoryinterfaces属性中;
      3. 如果目标类没有符合要求的接口,将proxyTargetClass设置为true,表示使用cglib进行类代理。
      4. 将匹配后的增强拦截器和普通拦截器进行合并,并将所有的拦截器统一调用warp方法封装为Advisor类型;
      5. 调用子类扩展方法AbstractAutoProxyCreator#customizeProxyFactory方法来定制自定义ProxyFactory
  11. 调用createAopProxy方法,获取构造方法默认创建的DefaultAopProxyFactory代理工厂对象,开始选择代理方式并创建代理对象;

    1. 如果没有开启优化策略、并且没有设置基于类代理,且目标类实现了接口但不是SpringProxy类型的,就会使用jdk代理;
    2. 如果满足上面的某一个条件,就会再次判断目标类是否是一个接口或者代理类,如果是就使用jdk代理,否则使用cglib代理;
    3. 常用的配置总结:

      1. 如果设置了proxyTargetClasstrue,也就是设置了基于类代理,并且此时目标类既不是接口类型也不是代理类时就会使用cglib代理;
      2. 如果没有设置proxyTargetClass,即proxyTargetClassfalse,目标类没有实现接口,此时也会使用cglib进行代理;
      3. 如果目标类实现了接口,并且此时没有强制设置使用cglib代理,比如proxyTargetClassfalse,这个时候就会使用jdk代理;
  12. 使用jdk代理;

    1. 使用Proxy#newProxyInstance方法创建jdk动态代理;
    2. 拼接代理类型;
    3. 生成代理类的字节码(ProxyGenerator#generateProxyClass);
    4. 将代理类加载到JVM(Proxy#defineCLass);
    5. 获取代理类的构造方法;
    6. 使用反射创建代理对象(Constructor#newInstance),将创建好的动态代理对象返回;
  13. 使用cglib代理;

    1. 构建Enhancer
    2. 创建代理类和代理类对象(ObjenesisCglibAopProxy#createProxyClassAndInstance);
    3. 创建代理类(Enhancer#createClass);
    4. 创建cglib代理对象(SpringObjenesis#newInstance),将创建好的动态代理对象返回。