我们在 Spring AOP原理 (二)AnnotationAwareAspectJAutoProxyCreator的执行时机,中已经了解到AnnotationAwareAspectJAutoProxyCreator
是如何创建的,她和BeanPostProcessor
又有什么异同。AnnotationAwareAspectJAutoProxyCreator
继承了抽象类AbstractAutoProxyCreator
,
我们在此打一个断点,直到beanClass是我们自己加入容器中的com.funtl.hello.spring.cloud.eureka.aop.MathCalculator
下面是
postProcessBeforeInstantiation
方法的代码,我们一步一步的看都做了什么
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = this.getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//这里设置不需要增强的bean 状态设置为false
if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
return null;
}
}
1 每一个bean 创建之前,调用postProcessBeforeInstantiation()
;关心MathCalculator和LogAspect 的创建
1.1 判断当前bean是否在adviseBeans中(保存了所有需要增强的bean)
1.2 当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,是否是切面
AbstractAutoProxyCreator
代码如下
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal =
Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && this.logger.isTraceEnabled()) {
this.logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
AnnotationAwareAspectJAutoProxyCreator
是 AbstractAutoProxyCreator
子类 isInfrastructureClass
方法覆盖了父类的isInfrastructureClass()
方法同时调用super.isInfrastructureClass(beanClass)
,代码如下
protected boolean isInfrastructureClass(Class<?> beanClass) {
return super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass);
}
this.aspectJAdvisorFactory.isAspect(beanClass)
判断是否是一个切面
public boolean isAspect(Class<?> clazz) {
return this.hasAspectAnnotation(clazz) && !this.compiledByAjc(clazz);
}
1.3 是否需要跳过
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
//找到候选的增强器(切面通知方法)
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
Iterator var4 = candidateAdvisors.iterator();
Advisor advisor;
do {
//如果不满足增强器的类型调用父类的shouldSkip。
if (!var4.hasNext()) {
return super.shouldSkip(beanClass, beanName);
}
advisor = (Advisor)var4.next();
} while(!(advisor instanceof AspectJPointcutAdvisor) || !((AspectJPointcutAdvisor)advisor).getAspectName().equals(beanName));
return true;
}
找到候选的增强器(切面通知方法),每一个封装的通知方法的增强器是InstantiationModelAwarePointcutAdvisor
类型的
不满足advisor instanceof AspectJPointcutAdvisor) || !((AspectJPointcutAdvisor)advisor).getAspectName().equals(beanName)
的判断所以调用父类的super.shouldSkip(beanClass, beanName)
,父类直接返回false
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return false;
}
2. 创建对象
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
//这里判断这个bean是否是之前已经将增强状态设置为false ,如果是直接返回不需要使用动态代理生成新对象(第一段代码第9行)
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//获取当前bean 的所有增强器`Object[] specificInterceptors`(通知方法)
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
//将当前bean 以增强的bean的放入到 advisedBeans 中
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
2.1 获取当前bean 的所有增强器(通知方法)
2.1.1 找到候选的所有增强器(找到哪些通知方法是需要切入当前bean 的)
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//候选MathCalculator 的增强器(切面)
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//候选增强器
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
//找出可以使用的增强器
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
List var4;
try {
//使用aop工具找到增强器
var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName((String)null);
}
return var4;
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
} else {
List<Advisor> eligibleAdvisors = new LinkedList();
Iterator var3 = candidateAdvisors.iterator();
while(var3.hasNext()) {
Advisor candidate = (Advisor)var3.next();
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
Iterator var7 = candidateAdvisors.iterator();
while(var7.hasNext()) {
Advisor candidate = (Advisor)var7.next();
if (!(candidate instanceof IntroductionAdvisor) && canApply(candidate, clazz, hasIntroductions)) {
//获得能用的增强器,能够用的增强器都加入 eligibleAdvisors 返回
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
}
下面就开始算切入点表达式和 MathCalculator是否能够匹配
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor)advisor).getClassFilter().matches(targetClass);
} else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor)advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
} else {
return true;
}
}
2.1.2 获取能在bean 使用的增强器
2.1.3 给增强器排序
2.2 保存当前bean(已增强)在adviseBeans(存放增强的bean)中
2.3 如果当前bean 需要增强器,创建当前bean 的代理对象this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
}
//创建ProxyFactory 工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//拿到增强器
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
//增强器放到代理工厂
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//用代理工厂帮我们创建对象
return proxyFactory.getProxy(this.getProxyClassLoader());
}
2.3.1 获取所有增强器(通知方法)
2.3.2 保存到proxyfactory中
2.3.3 创建代理对象Spring 自动决定(有实现接口的使用jdk没有的使用cglib) new JdkDynamicAopProxy(config)
new ObjenesisCglibAopProxy(config)
两种
2.4 给容器返回当前组件使用cglib增强了的代理对象
2.5 以后容器中获取到的就是这个组件的代理对象,执行目标方法时,代理对象就会执行通知方法的流程
3. 目标方法执行:
容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象等)
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
Object var16;
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
//获取将要执行的目标方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//如果拦截器链为空的,直接执行目标方法
retVal = methodProxy.invoke(target, argsToUse);
} else {
//如果有拦截器链
retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
}
retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
var16 = retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var16;
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
AdvisedSupport.MethodCacheKey cacheKey = new AdvisedSupport.MethodCacheKey(method);
List<Object> cached = (List)this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
遍历所有增强器,并将增强器封装为Interceptor
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {
List<Object> interceptorList = new ArrayList(config.getAdvisors().length);
Class<?> actualClass = targetClass != null ? targetClass : method.getDeclaringClass();
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] var8 = config.getAdvisors();
int var9 = var8.length;
for(int var10 = 0; var10 < var9; ++var10) {
Advisor advisor = var8[var10];
MethodInterceptor[] interceptors;
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
MethodInterceptor[] var15 = interceptors;
int var16 = interceptors.length;
for(int var17 = 0; var17 < var16; ++var17) {
MethodInterceptor interceptor = var15[var17];
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
} else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
} else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor)advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
} else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
3.1 CglibAopProxy.intercept();拦截目标方法执行
3.2 获取将要执行的目标方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
3.2.1 List<Object> interceptorList = new ArrayList(config.getAdvisors().length);
config.getAdvisors()
含有五个增强器一个默认的ExposeInvocationInterceptor
和四个我们定义的增强器(切入方法)
3.2.2 遍历所有增强器,将其转为 interceptors = registry.getInterceptors(advisor);
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor)advice);
}
Iterator var4 = this.adapters.iterator();
while(var4.hasNext()) {
AdvisorAdapter adapter = (AdvisorAdapter)var4.next();
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
} else {
return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[0]);
}
}
3.2.3 将增强器转为List<MethodInterceptor>
3.3 如果没有拦截器链直接执行目标方法
拦截器链(每一个通知方法又被包装为拦截器,利用MethodInterceptor
机制)
retVal = methodProxy.invoke(target, argsToUse);
3.4 如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入,并创建一个CglibMethodInvocation
对象,并调用proceed();
retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
3.5 拦截器链的触发过程
@Nullable
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//没有拦截器链调用反射执行目标方法具体代码可以自己点进去看看 最终执行的是method.invoke(target, args);
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
3.5 拦截器链的触发过程
3.5.1 如果没有拦截器执行目标方法,或者拦截器的索引和拦截器数组-1大小一样执行目标方法
3.5.2 链式获取每一个拦截器,拦截器执行invoke 方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;拦截器链的机制保证通知方法与目标方法的执行顺序
开始看这个拦截器链的调用过程
这里有五个拦截器
private int currentInterceptorIndex = -1;
默认从-1开始++this.currentInterceptorIndex
索引+1执行索引为0 的拦截器
ExposeInvocationInterceptor
的invoke()
方法进入
invoke()
方法
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = (MethodInvocation)invocation.get();
invocation.set(mi);
Object var3;
try {
var3 = mi.proceed();
} finally {
invocation.set(oldInvocation);
}
return var3;
}
这里执行var3 = mi.proceed();
mi
就是((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
的this 所以等于又递归调用proceed()
方法
此时currentInterceptorIndex=1
调用第二个拦截器AspectJAfterThrowingAdvice
(异常通知)的invoke()
方法
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
} catch (Throwable var3) {
if (this.shouldInvokeOnThrowing(var3)) {
this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, var3);
}
throw var3;
}
}
return mi.proceed();
同上继续返回调用currentInterceptorIndex=2
,调用第三个拦截器AfterReturningAdviceInterceptor
(返回通知)的invoke()
方法
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
//返回通知可以获得返回值
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
return mi.proceed();
同上继续返回调用currentInterceptorIndex=3
, 调用第四个拦截器AspectJAfterAdvice
(后置通知)的invoke()
方法
public Object invoke(MethodInvocation mi) throws Throwable {
Object var2;
try {
var2 = mi.proceed();
//后置通知就是无论成功与否都会在finally中调用
} finally {
this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
}
return var2;
}
return mi.proceed();
同上继续返回调用currentInterceptorIndex=4
, 调用第五个拦截器MethodBeforeAdviceInterceptor
(前置通知)的invoke()
方法
public Object invoke(MethodInvocation mi) throws Throwable {
//在调用前 执行通知方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
此时控制台打印结果为
div方法运行参数列表是:{}
前置通知率先执行。代码继续往下走 currentInterceptorIndex=4
this.interceptorsAndDynamicMethodMatchers.size() - 1=4
执行目标方法控制台输出:
div方法运行参数列表是:{}
MathCalculator=====6 div 2 a/b=3
递归返回到上一个调用返回的地方
F7,代码继续往下走,此时控制台输出
div方法运行参数列表是:{}
MathCalculator=====6 div 2 a/b=3
div运行结束
此时递归调用到
F7,代码继续往下走,此时控制台输出
div方法运行参数列表是:{}
MathCalculator=====6 div 2 a/b=3
div运行结束
除法正常返回,运行结果是:{3.0}
此时递归返回到
F7,代码继续往下走,因为无异常所以无输出,断点到
如果出现异常
div方法运行参数列表是:{}
div运行结束
div异常信息是:{java.lang.ArithmeticException: / by zero}
拦截牵连调用关系图