本文编写于 1320 天前,最后修改于 1313 天前,其中某些信息可能已经过时。
- 从IOC容器中获取bean;
- 调用bean后置处理器
AbstractAutoProxyCreator的postProcessBeforeInstantiation()方法; - 判断是否指定
targetSource,如果指定了targetSource会跳过bean的实例化和初始化流程,也就是会直接创建AOP代理; - 如果没有指定
targetSource,执行正常创建bean的流程,执行bean的初始化,执行initMethod方法; - 调用bean后置处理器
AbstractAutoProxyCreator的postProcessAfterInitialization()方法; - 执行
wrapIfNecessary方法包装需要被代理的bean; 获取所有的增强
advisors;- 获取xml方式配置的增强
advisors; - 获取
@Aspect注解配置的增强advisors,调用BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors方法; - 获取IOC容器中的所有bean,判断是否添加
@Aspect注解; - 添加了
@Aspect注解的切面类,调用doWithMethods()方法遍历切面类的每个方法,找到其中标注了@Point、@Around、@Before、@After、@AfterReturning、@AfterThrowing六种注解的方法; - 找到标注了上面六种注解的方法后,构建一个
AspectJExpressionPointcut切点对象,并设置注解中的切入点表达式; - 通过增强方法
candidateAdviceMethod和切点AspectJExpressionPointcut等信息通过InstantiationModelAwarePointcutAdvisorImpl的构造方法构建出一个Advisor; - 如果bean是单例就将
<beanName,advisors>以键值对的形式缓存起来,如果bean不是单例,就将<beanName,factory>以键值对的形式缓存起来,方便下一次直接使用factory快速构建Advisors,并继续循环处理下一个bean;
- 获取xml方式配置的增强
- 调用
findAdvisorsThatCanApply方法,从所有增强的advisor中找到与当前bean相匹配的增强Advisors; 遍历当前bean中所有方法依次与
advisor的切点表达式进行匹配;- 如果是
advisor是IntroductionAdvisor引介增强的实现类,那么就进行类级别进行匹配(不常用); - 默认的
InstantiationModelAwarePointcutAdvisorImpl实现的是普通增强PointcutAdvisor接口,使用切点Pointcut进行方法级别的匹配; - 先使用切点表达式和目标类进行匹配,确保类级别满足切点表达式;
遍历当前bean中的所有方法,使用
aspectj提供的方法(SignaturePattern#matchesExactlyMethod),依次对切点表达式对方法进行精确匹配;- 判断方法参数是否匹配;
- 判断方法名称是否匹配;
- 判断方法抛出异常是否匹配;
- 判断方法返回值是否匹配;
- 将所有匹配的
Advisors使用Order接口进行排序并返回;
- 如果是
创建
ProxyFactory对象,并设置相关属性;- 从
AnnotationAwareAspectJAutoProxyCreator复制proxyTargetClass、optimize、exposeProxy、frozen、opaque等属性; 判断是基于类代理还是接口代理,也就是cglib代理还是jdk代理;
- 判断
beanDefinition中是否定义了preserveTargetClass属性,如果配置为true就将proxyTargetClass设置为true,表示使用cglib进行类代理; - 判断目标类是否有如何要求的接口,如有符合要求的接口,就将接口添加到
proxyFatory的interfaces属性中; - 如果目标类没有符合要求的接口,将
proxyTargetClass设置为true,表示使用cglib进行类代理。 - 将匹配后的增强拦截器和普通拦截器进行合并,并将所有的拦截器统一调用
warp方法封装为Advisor类型; - 调用子类扩展方法
AbstractAutoProxyCreator#customizeProxyFactory方法来定制自定义ProxyFactory;
- 判断
- 从
调用
createAopProxy方法,获取构造方法默认创建的DefaultAopProxyFactory代理工厂对象,开始选择代理方式并创建代理对象;- 如果没有开启优化策略、并且没有设置基于类代理,且目标类实现了接口但不是
SpringProxy类型的,就会使用jdk代理; - 如果满足上面的某一个条件,就会再次判断目标类是否是一个接口或者代理类,如果是就使用jdk代理,否则使用cglib代理;
常用的配置总结:
- 如果设置了
proxyTargetClass为true,也就是设置了基于类代理,并且此时目标类既不是接口类型也不是代理类时就会使用cglib代理; - 如果没有设置
proxyTargetClass,即proxyTargetClass为false,目标类没有实现接口,此时也会使用cglib进行代理; - 如果目标类实现了接口,并且此时没有强制设置使用cglib代理,比如
proxyTargetClass为false,这个时候就会使用jdk代理;
- 如果设置了
- 如果没有开启优化策略、并且没有设置基于类代理,且目标类实现了接口但不是
使用jdk代理;
- 使用
Proxy#newProxyInstance方法创建jdk动态代理; - 拼接代理类型;
- 生成代理类的字节码(
ProxyGenerator#generateProxyClass); - 将代理类加载到JVM(
Proxy#defineCLass); - 获取代理类的构造方法;
- 使用反射创建代理对象(
Constructor#newInstance),将创建好的动态代理对象返回;
- 使用
使用cglib代理;
- 构建
Enhancer; - 创建代理类和代理类对象(
ObjenesisCglibAopProxy#createProxyClassAndInstance); - 创建代理类(
Enhancer#createClass); - 创建cglib代理对象(
SpringObjenesis#newInstance),将创建好的动态代理对象返回。
- 构建