本文编写于 920 天前,最后修改于 913 天前,其中某些信息可能已经过时。
- 从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
),将创建好的动态代理对象返回。
- 构建