Spring AOP原理

AOP原理

解析 标签

入口 DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()

1.解析自定义名称空间的标签
1.1.由 NamespaceHandlerResolver 根据 namespaceUri 获取具体的 NamespaceHandler
1.1.1.第一次获取时会加载所有 handlerMappings
1.1.2.根据 namespaceUri 从 handlerMappings 中获取 handlerOrClassName,此处为 org.springframework.aop.config.AopNamespaceHandler
1.1.3.实例化 namesapceHandler
1.1.4.调用 namespaceHandler.init() 注册对所有标签元素的 BeanDefinitionParser
1.2.调用 AopNamespaceHandler.parse(),交给具体的 parser 进行处理
1.2.1.注册 AnnotationAwareAspectJAutoProxyCreator
1.2.2.对 proxy-target-class 标签 和 expose-proxy 标签的处理,处理到 beanDefinition 的 PropertyValues 中

创建 AOP 代理对象

入口 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization()

1.DefaultAdvisorAutoProxyCreator 实现了 BeanPostProcessor 接口,在 init-method 之后会调用它的 postProcessAfterInitialization() 方法.
1.1.通过 wrapIfNecessary() 方法 为 bean 生成代理对象(如果需要的话)
1.1.1.给定的 bean 类是否代表一个基础设施类(Pointcut, Advice, Advisor 等接口的实现类) 或 类上有 @Aspectj注解,不应该生成代理; 或配置了指定 bean 不需要自动代理,则直接返回原始bean
1.1.2.上面过滤掉了不需要增强生成代理的场景
1.1.3.拦截并返回匹配当前 bean 的所有的 advisor、advice、interceptor
1.1.3.1.获取所有的增强 以及 寻找所有增强中适用于该 bean 的增强 并应用
1.1.3.1.1.获取所有 advisors
1.1.3.1.1.1.从容器中查找所有 Advisor 类型的 bean
1.1.3.1.1.2.解析 @Aspect 注解
1.1.3.1.2.根据 advisors 中的切点表达式 匹配目标类,返回匹配的 advisors
1.1.3.1.2.1.查看该 advisor 能否应用于该 bean.主要判断 切点表达式 匹配 目标类(中的方法)
1.1.3.1.2.1.1.目标类必须满足匹配规则 且 目标类中至少有一个方法匹配
1.2.如果有匹配的 advisors,则需要针对增强创建代理.通过 createProxy() 创建代理类,ProxyFactory 会根据 几种情况选择 Java 代理或 CGLib 代理
1.2.1. 这个节点中 proxy-target-class=“false” 或 proxy-target-class 不配置,即不使用 CGLIB 生成代理.若满足条件则添加所有代理接口到 proxyFactory 中
1.2.2.proxyFactory.getProxy() 获取代理对象
1.2.2.1.DefaultAopProxyFactory.createAopProxy() 中

用于选择使用JDKProxy还是CglibProxy实现代理

默认使用 JDK 生成代理,但是 JDK 生成代理必须要求要实现接口.

如果下面三个有一个条件满足,就使用 cglib 生成代理,即使目标类有接口.当然若目标类本身就是接口,还是使用 JDK.
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))

(1) isOptimize()方法为true,这表示让 Spring 自己去优化而不是用户指定.默认false.

(2) ProxyConfig.isProxyTargetClass() 方法为 true,表示配置了proxy-target-class="true".默认 false.
这个属性为 true 时,目标类本身被代理而不是目标类的接口.如果这个属性值被设为 true,CGLIB 代理将被创建.

(3) ProxyConfig 满足 hasNoUserSuppliedProxyInterfaces() 方法执行结果为 true,这表示``对象没有实现任何接口或者实现的接口是 SpringProxy 接口

1.2.2.2.返回创建后的 AOP 代理对象

调用目标类中的方法

由于 Spring 返回的是代理类 TestBean$$EnhancerBySpringCGLIB$$b16276c1,会调到这里.
调用栈

arountTest:26, AspectJTest (com.zc.simple)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:57, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:606, Method (java.lang.reflect)
invokeAdviceMethodWithGivenArgs:621, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invokeAdviceMethod:610, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invoke:65, AspectJAroundAdvice (org.springframework.aop.aspectj)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:42, AspectJAfterAdvice (org.springframework.aop.aspectj)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:91, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:633, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
test:-1, TestBean$$EnhancerBySpringCGLIB$$b16276c1 (com.zc.simple)
main:10, Test (com.zc.simple)

你可能感兴趣的:(Spring)