spring整套源码系列之【aop代理对象创建以及调用invoke源码】
2024-04-10 18:45:44 0 举报
spring整套源码系列之【aop代理对象创建以及调用invoke源码】
作者其他创作
大纲/内容
以免重复创建代理
单例池
是
//使用cglib代理 return new ObjenesisCglibAopProxy(config);
this.earlyProxyReferences.remove(cacheKey) != bean
//用来记录当前正在创建的被代理对象的名称 ProxyCreationContext.setCurrentProxiedBeanName(beanName);
continue
finally { //从线程局部变量中清楚当前正在创建的beanName的代理对象名称 ProxyCreationContext.setCurrentProxiedBeanName(null); }
return AopProxyUtils.ultimateTargetClass(this.advised);
否
BeanPostProcessor
return
return equals(args[0]);
//若候选的增强器集合为空 直接返回 candidateAdvisors.isEmpty())
//设置targetSource对象\t\tproxyFactory.setTargetSource(targetSource);
从单例池中拿到的其实是代理对象
这里是作为调用链出口的判断,每执行完一次currentInterceptorIndex 都会加1,默认为-1this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1
return代理对象
判断是否配置了exposeProxy = truethis.advised.exposeProxy
//createAopProxy() 用来获取我们的代理工厂:cgLib或者JdkDynamicAopProxy\t\treturn createAopProxy().getProxy(classLoader);
//使用责任链方式调用执行 retVal = invocation.proceed();
2:执行Around拦截器
调用
调用方法其实调用的是代理对象的方法
doCreateBean()
//为我们的代理工加入通知器, proxyFactory.addAdvisors(advisors);
否:不需要跳过
循环我们候选的增强器对象for (Advisor candidate : candidateAdvisors)
return false
这里会调用到AnnotationAwareAspectJAutoProxyCreator里去,也就是拿到前面我们解析好的advisorList缓存
3:执行Before拦截器
判断是否有advisorspecificInterceptors != DO_NOT_PROXY
mi为ReflectiveMethodInvocation
for循环方法
//获取到targetClass所实现的接口的class对象,然后加入到集合中\t\tclasses.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
这里同样会先执行调用链,这已经是最后一个了,所以就能拿到目标方法的执行结果Object retVal = mi.proceed();
invocation.set(oldInvocation);
判断advisor是否实现了advisor instanceof IntroductionAdvisor
使用代理配置对ProxyConfig的服务调用!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)
postProcessAfterInitialization()
又回到ReflectiveMethodInvocation的proceed方法,此时拦截器为:AspectJAfterReturningAdvice.invoke方法
未匹配上
return bean;
return true
config.isProxyTargetClass():这个为我们是否配置了强制使用cglib代理,也就是@EnableAspectJAutoProxy(proxyTargetClass = true)
//创建一个集合用于保存targetClass 的class对象\t\tSet<Class<?>> classes = new LinkedHashSet<>();
getBean
//评估动态方法匹配器这里:静态部分已经有了//被评估并发现匹配。
return eligibleAdvisors;
入口1
否:不符合
如果targetClass是接口 使用的就是jdk代理targetClass.isInterface() || Proxy.isProxyClass(targetClass)
for循环
getBean()
//获取到我们的目标对象\t\tTargetSource targetSource = this.advised.targetSource;
1:执行Around方法
配置了
不为空
为空
判断我们是否前置指定使用cglib代理ProxyTargetClass =true 默认为falseconfig.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)
初始化
实例化
进行类级别的筛选!pc.getClassFilter().matches(targetClass)
put
初始化后AOP:创建代理
获取拦截链中的方法,并且currentInterceptorIndex提前加1 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
通过案例看比如我们调用链如下
//把我们的代理对象暴露到线程变量中 oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true;
//jdk代理 return new JdkDynamicAopProxy(config);
假如当前正在创建的Bean的class 是Advice PointCut Advisor AopInfrastructureBean 直接跳过不需要解析,也就是这里就去除了aop自己类的bean,然后再shouldSkip()里面就判断并处理非aop自己家到类
4:执行After拦截器
//创建一个代理对象工厂\t\tProxyFactory proxyFactory = new ProxyFactory();
postProcessBeforeInstantiation()
//定义一个合适的增强器集合对象\t\tList<Advisor> eligibleAdvisors = new ArrayList<>();
else if
又回到ReflectiveMethodInvocation的proceed方法,此时拦截器为:AspectJAfterAdvice.invoke方法
//不为空 boolean hasIntroductions = !eligibleAdvisors.isEmpty();
这个排序其实挺重要的,执行的时候是根据这个list的顺序执行的,所以这个顺序必须是满足我们不同advice执行的时机,比如before在after前执行
//循环我们的方法\t\t\tfor (Method method : methods)
处理过后会放入这个advisedBeans集合中,这里也是为了防止重复创建代理对象而生
return true;
没有合适当前bean的advisor自然是不需要给bean创建代理对象
匹配上了
for循环class
return原始对象
此时取到的方法拦截器为第二个:AspectJAroundAdvice,也就是会执行到它的invoke方法
若执行的是hashCode方法 不需要代理!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)
执行目标方法并增强
不为hashCode方法
//转为PointcutAdvisor类型\t\t\tPointcutAdvisor pca = (PointcutAdvisor) advisor;
类匹配不到
//通过class获取到所有的方法\t\t\tMethod[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
6:执行目标方法
若执行的class对象是DecoratingProxy 也不要拦截器执行method.getDeclaringClass() == DecoratingProxy.class
//加入到集合中去\t\t\tclasses.add(ClassUtils.getUserClass(targetClass));
判断是否不需要加强Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))
不为equals方法
然后继续执行调用链return mi.proceed();
第一次调用bean后置处理器用来解析切面
实际调用了
return mi.proceed();
其实就是找到前面解析出来的advisorList,然后刷选出合适的advisorList出来,所谓合适说的是能作用到当前bean的advisor集合
1:执行第一个
若执行方法为equals方法不需要代理!this.equalsDefined && AopUtils.isEqualsMethod(method)
我们通过Aspect生成的advisor为InstantiationModelAwarePointcutAdvisorImpl类型的,前面解析的时候可以看到
return false;
不需要加强
入口2
invoke(...)
符合:再进行方法级别筛选
cglib代理产生的代理对象ObjenesisCglibAopProxy
//调用拦截器 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
在around方法中有去调用目标方法,然后就又执行到了ReflectiveMethodInvocation的proceed方法,此时拦截器为:AspectJMethodBeforeAdvice.invoke方法
createAopProxy()
这里第一个调用的为ExposeInvocationInterceptor类型的,是在寻找合适advisor的时候加上去的
return hashCode();
这里就找到了所有能匹配当前bean的advisor
//获取我们的目标对象\t\t\ttarget = targetSource.getTarget();
//循环所有的class对象\t\tfor (Class<?> clazz : classes)
//记录当前正在执行的拦截器\t\tinvocation.set(mi);
属性赋值
else:两种类型都不是直则全处理
判断当前class是不是代理的class对象!Proxy.isProxyClass(targetClass)
return proxy;
5:执行AfterReturning拦截器
需加强
具体这里怎么匹配的话,用的是AspectJ的方式了
isInfrastructureClass(bean.getClass())
这里的意思就是我匹配一个类的方法不只是需要匹配本类的方法,父类的方法也是它的,所以都是需要判断是否能匹配上
//找到ioc容器中候选的通知 List<Advisor> candidateAdvisors = findCandidateAdvisors();
创建好bean
然后又调用到ReflectiveMethodInvocation的proceed方法
bean的后置处理器AnnotationAwareAspectJAutoProxyCreator
判断,不过我们的advice都不符合interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher
执行目标方法return invokeJoinpoint();
判断拦截器链是否为空chain.isEmpty()
2:执行before方法
这里会先去执行调用链,然后后面再finally里执行afterAdvice的方法(也就是执行我们写的after方法)var2 = mi.proceed();
//获取我们目标对象的class\t\t\tClass<?> targetClass = (target != null ? target.getClass() : null);
加入return集合中eligibleAdvisors.add(candidate);
InstantiationAwareBeanPostProcessor
//真正的创建代理对象\t\treturn proxyFactory.getProxy(getProxyClassLoader());
首先第一个调用ExposeInvocationInterceptor的invoke方法
jdk动态代理对象JdkDynamicAopProxy
判断是否处理过了this.targetSourcedBeans.contains(beanName)
判断到这里时最后一个了,执行目标方法return this.invokeJoinpoint();
有
创建代理对象
判断advisor是否实现了advisor instanceof PointcutAdvisor
执行回到:执行after方法
这个方法就直接执行到了我们写的@Around(\"myPoint()\")方法里面去了
没有
4:执行after方法
对我们的advisor进行排序return sortAdvisors(eligibleAdvisors);
this(ProxyFactory)为我们指定我们advisor信息getAopProxyFactory().createAopProxy(this);
通过切点获取到一个方法匹配器对象MethodMatcher methodMatcher = pc.getMethodMatcher();
3:执行afterReturning方法
判断匹配器是否为任意方法methodMatcher == MethodMatcher.TRUE
这里使用了ThreadLocal<String>保存beanName,也就是在此线程中任何一个地方都能取到这个值
return candidateAdvisors;
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
0 条评论
下一页