spring aop源码分析
2024-05-08 13:21:04 2 举报
spring aop源码分析
作者其他创作
大纲/内容
getAdvisorMethods方法排除@Pointcut方法
获取当前的拦截器++this.currentInterceptorIndex
返回
创建动态代理
在第一个bean的后置处理器
AopUtils.findAdvisorsThatCanApply
beanNames
for
去类上面查询有没有@Aspect注解
设置到ThreadLocal
初始化bean
point
直接调用
AbstractAutowireCapableBeanFactory
new AspectJAfterReturningAdvice
getInterceptorsAndDynamicInterceptionAdvice
决定使用哪种动态代理的关键如果配置了proxy-target-class=true 后续将创建cglib代理如果有接口就使用jdk代理
排除有@Pointcut的方法
获取切面中所有通知
调用
true
advisor instanceof PointcutAdvisor
6自置
advisor advise pointcut
createProxy
toBinary
end
Spring AOP四种实现方式* 注入式AspectJ切面(其实与Spring并无多大的关系,这个就是使用AspectJ这个框架实现的AOP编程)
4
return nullN
SimpleProgramCalculate
循环依赖是否已创建Proxy
AbstractAutoProxyCreator#postProcessBeforeInstantiation
aspectName
创建每一个bean的时候用初始化后的那个BeanPostProcessor拿到所有的advisors循环跟当前的bean做比对如果比对上了说明当前Bean需要创建动态代理
循环当前类和类的接口,所以注解标记在接口上也是可以的
调用被代理的方法
满足
忽略,说明不是通知
不代理equals方法不代理hashCode方法不代理DecoratingProxy方法不代理Advised方法
eligibleAdvisors.add(candidate);
是否targetSourcedBeans是否需要忽略是否aop基础类是否需要跳过
否
3
this.aspectBeanNames = aspectNames;
ProxyFactory.getProxy
PointCut
织入
1
Proxy.newProxyInstance
canApply
已解析的切面类名称缓存
createProxyClassAndInstance
没有就转换
return null是
0
调用代理
进入beanPostProcessor
符合
sub
DefaultAdvisorAdapterRegistry#getInterceptors
2异常
advice本身实现了Intercepter
拿到之前解析切面的时候就已经解析到的advisor
结果
将advice、point、Method等信息都封装到Advisor
MethodCacheKey cacheKey = new MethodCacheKey(method);List<Object> cached = this.methodCache.get(cacheKey);
2
initializeBean
没有符合的advisor就不创建代理标记后直接忽略
从候选的通知器中找到当前Bean关联的advisors
AtBefore前置通知
将提取的结果加入缓存中
getAdvicesAndAdvisorsForBean
引入Introductions
AtAfter后置通知
findEligibleAdvisors
* @AspectJ注解驱动的切面(注解)
如果转化不了空
doCreateBean
5前置
expression
通知的大致两种转换方式:1.通过适配器2.advice本身实现了Intercepter
findAspectJAnnotationOnMethod从所有方法中过滤出以下注解
1内置
new AspectJAfterThrowingAdvice
精筛
解析切面
AtAfterReturning返回通知
matches
切面(Aspect)连接点(Join point)通知(Advice)目标对象(Target)切点(Pointcut)顾问(Advisor)织入(Weaving)引入(Introductions)
eligibleAdvisors就能体现当前bean是否需要被增强,决定是否要创建动态代理
5
AtAround环绕通知
当获得被代理的bean时实际获取的是动态代理对象
9
后置
* 纯POJO切面(XML) spring2.0
buildAspectJAdvisors
advisedBeans是否解析过
after
遍历所有beanName,解析出被@Aspect标记的类
super.findCandidateAdvisors()
已解析的Advisors缓存
从缓存中拿
wrapIfNecessary
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
ProgramCalculate
createBean
proxy-target-class=true
实现
Calculator
multi
beanFactory
真正的创建bean
AtAfterReturning异常通知
if (this.advisorFactory.isAspect(beanType)) {
@AspectJ
LogUtil跟主要业务没有关系的公共代码增强的模块
自置
会在解析xml的时候解析
6
通知Advice
eligibleAdvisors只要上一步添加了符合的通知
异常
1.MethodMatcher是否为true,匹配所有的方法
调用基于jdk动态代理
未被解析if (aspectNames == null) {
afterReturn
@AspectJ@Before@After....
从容器中获取类型为Object的beanName
按切点匹配(需要进入aspectJ)
执行目标方法:div
设置ProxyTargetClass就会使用cglib动态代理,如果没有设置,并且有接口就会使用jdk动态代理
前置
将advice、pointcut等信息解析到Advisor中
5
add
JdkDynamicAopProxy#invoke
JdkDynamicAopProxy
事务
advisors.add(advisor);
否isInfrastructureClass
(Calculate) ctx.getBean(\"myCalculate\");
是否中方法精筛
ExposeInvocationInterceptor#invoke
new AspectJAfterAdvice
* 经典的基于接口的配置 spring1.2
提取Aspect类中所有的Advice方法
MethodBeforeAdviceInterceptor#invoke
afterException
7
targetClass
事务...
MyCalculate(Target)
不满足创建动态代理的条件return bean
div
转换效果
ReflectiveMethodInvocation#proceed
是否中类初筛
shouldSkip拿到所有的bean定义是不是标记了@AspectJ每一个通知都会生成一个advisor
是否被解析只会解析一次后续缓存
递归出口:调用到了最后一个拦截器
当前方法是否标注了注释中的任意一个
((Calculate)AopContext.currentProxy())
AbstractAutoProxyCreator#postProcessAfterInitialization
切面aspect
全部转化为拦截器通过责任链模式调用
缓存中有直接返回
适配的advice
如果是aop基础Bean或者候选advisor之前已经通过xml解析过则标记无需创建代理
内置
标记为无需增强
InstantiationModelAwarePointcutAdvisorImpl
chain.isEmpty()
8
new AspectJMethodBeforeAdvice
Method
4后置
初筛
创建代理条件
before
从ThreadLocal中获取
有接口
按经典aop的advisor匹配器去匹配
方法匹配实现大致分为:
当前bean是否Advice是否PointCut是否Advisor是否AopInfrastructureBean是否切面
CglibAopProxy
AspectJAfterAdvice#invoke
根据当前bean找到匹配的advisor
解析exposeProxy属性
异常-2
currentInterceptorIndex=-1
AspectJAfterThrowingAdvice#invoke
AspectJAfterReturningAdvice#invoke
3返回
createAopProxy()
return null
调用动态代理类的invoke方法
shouldSkip
new AspectJAroundAdvice
异常-1
已经创建过return bean
有
AspectJExpressionPointcut
aspectNames.add(beanName);
findCandidateAdvisors
拿到所有之前解析到的advisors
10
加入到缓存中
0 条评论
下一页