一、简介
AOP源码分析主要分为5个篇章:前面4篇已经讲了
1. 注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator
【十】Spring源码分析之AOP----注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator
2. 扫描容器中的切面,创建PointcutAdvisor对象
【十一】Spring源码分析之AOP----AnnotationAwareAspectJAutoProxyCreator扫描@Aspect,创建Advisor3.解析pointcut切点的表达式,看该目标bean与哪些Advisor匹配
【十二】Spring源码分析之AOP----匹配出作用于被代理类Advisor
4.Spring源码分析之AOP----生成代理对象。
5. 被代理类的方法一次调用流程。就是本篇。
jdk动态代理的时候,getBean得到的是代理对象。调用目标对象的方法前,都是调用的代理对象的invoke方法进行增强拦截。
源码:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
// 如果被代理的目标对象要执行equal方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
// 则执行JdkDynamicAopProxy(即代理对象)的equal方法。spring不对equal方法进行AOP拦截
return equals(args[0]);
}
// spring不对hashCode方法进行AOP拦截。如果被代理的目标对象要执行hashCode方法,则执行JdkDynamicAopProxy(即代理对象)的hashCode方法。
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 如果被代理的目标对象实现了Advised接口,直接用反射执行目标对象的方法。不做增强处理。
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 需要提前暴露
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
// 得到目标对象
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this method.
// 得到该方法的拦截链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
// 如果拦截链是空的,直接反射调用方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
// 如果拦截链不为空
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 挨着走拦截链
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
做了3件事:
1.spring不对equal方法进行AOP拦截。如果被代理的目标对象要执行equal方法,则执行JdkDynamicAopProxy(即代理对象)的equal方法。
spring不对hashCode方法进行AOP拦截。如果被代理的目标对象要执行hashCode方法,则执行JdkDynamicAopProxy(即代理对象)的hashCode方法。
如果被代理的目标对象实现了Advised接口,直接用反射执行目标对象的方法。不做增强处理。
2.得到该方法的拦截链,创建一个方法调用器,并将拦截器链传入其中, 执行拦截器链。
3.返回方法执行结果
二、得到方法拦截链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
源码:AdvisedSupport类
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
做了1件事:
从方法拦截链缓存methodCache中看有不有该方法的拦截链,有就直接返回,没有则调用this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass)得到方法拦截链,放入缓存中,并且返回。
2.1 创建方法拦截链getInterceptorsAndDynamicInterceptionAdvice
DefaultAdvisorChainFactory类的getInterceptorsAndDynamicInterceptionAdvice方法
源码:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 遍历Advisor
for (Advisor advisor : config.getAdvisors()) {
// 如果该adivosr是PointcutAdvisor类型的
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 把Advisor转成拦截器interceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 得到该advisor的pointcut的方法匹配器
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
// 判断该Advisor的pointcut跟目标对象要执行的方法是否匹配
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
//MethodMatcher在运行时是否需要做一些检测
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
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)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
做了3件事:
1.遍历Advisor。
2.如果是Advisor是PointcutAdvisor类型:得到该Advisor的Pointcut,判断要执行的目标对象的方法是否被这个Advisor增强。如果运行时需要做一些检测,则往返回列表中加入InterceptorAndDynamicMethodMatcher封装后的拦截器。否则直接加入拦截器到返回列表。
3.如果Advisor是IntroducationAdvisor类型的,用该Advisor的classFilter判断目标对象的类是否被这个Advisor增强,是则得到拦截器,加入到返回列表
4.如果 Advisor既不是PointcutAdvisor类型也不是IntroducationAdvisor类型,则不用匹配,直接生成拦截器,加入到返回列表。
三、执行拦截器invocation.proceed()
源码:ReflectiveMethodInvocation类
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 如果拦截器链为空,或者已经执行完了拦截器,则直接反射调用目标对象的方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 从第一个拦截器开始
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 如果该拦截器是InterceptorAndDynamicMethodMatcher类型
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 动态匹配
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
// 匹配则调用拦截器invoke
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
// 不匹配,则调用proceed,搞下一个拦截器
return proceed();
}
}
// 如果该拦截器不是InterceptorAndDynamicMethodMatcher类型,则直接调用该拦截器的invoke方法
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
做了3件事:
1.如果拦截器链为空,或者已经执行完了拦截器,则调用invokeJoinpoint方法直接AopUtils.invokeJoinpointUsingReflection反射调用目标对象的方法。
2.从第一个拦截器开始调用。如果该拦截器不是InterceptorAndDynamicMethodMatcher类型,则直接调用该拦截器的invoke方法。
3.如果该拦截器是InterceptorAndDynamicMethodMatcher类型,进行动态匹配,动态匹配失败,忽略该拦截器直接调用下一个拦截器,动态匹配成功则调用该拦截器的invoke方法。
四、执行的拦截器的内容
我debug的时候,上一步一共搞了6个拦截器的invoke方法
4.1 ExposeInvocationInterceptor类
源码:
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
做了1件事:
invocation是该类的一个ThreadLocal<MethodInvocation>,表示的是当前aop方法的invocation。
直接调用proceed方法执行下一个拦截器。
4.2 AspectJAfterThrowingAdvice类
源码:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
做了2件事:
1.直接调用proceed方法,执行下一个拦截器。
2.如果抛出异常,调用invokeAdviceMethod方法去调用切面中后置异常增强注解@AfterThrowing注解修饰的方法
4.3 AfterReturningAdviceInterceptor类
该类是InterceptorAndDynamicMethodMatcher类型的
源码:
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
做了3件事:
1.直接调用proceed方法执行下一个拦截器
2.调用this.advice.afterReturning方法执行切面中@AfterReturning后置增强注解修饰的方法。
3.返回proceed方法的返回值。
4.4 AspectJAfterAdvice类
该类是InterceptorAndDynamicMethodMatcher类型的
源码:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
做了2件事:
1.直接调用proceed方法执行下一个拦截器
2.finally中执行invokeAdviceMethod方法去调用切面中@After后置增强注解修饰的方法。
4.5 AspectJAroundAdvice类
该类是InterceptorAndDynamicMethodMatcher类型的
源码:
public Object invoke(MethodInvocation mi) throws Throwable {
// 如果该方法执行器MethodInvocation不是ProxyMethodInvocation类型的,则抛出异常。
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
// 得到一个MethodInvocationProceedingJoinPoint类型的ProceedingJoinPoint
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
做了4件事:
1.如果该方法执行器MethodInvocation不是ProxyMethodInvocation类型的,则抛出异常。
2.得到一个MethodInvocationProceedingJoinPoint类型的ProceedingJoinPoint
3.得到JoinPointMatch
4.调用invokeAdviceMethod执行方法。
4.5.1 invokeAdviceMethod(pjp, jpm, null, null)
源码:
protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
throws Throwable {
// argBinding方法得到目标对象调用方法的入参
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
invokeAdviceMethodWithGivenArgs源码:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
// this.aspectInstanceFactory.getAspectInstance()得到切面类的对象,即是@Aspect注解修饰的那个类的对象
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
做了2件事:
1.this.aspectInstanceFactory.getAspectInstance()得到切面类的对象,即是@Aspect注解修饰的那个类的对象
2.调用切面类的@Around环绕增强注解修饰的方法。环绕增强@Around注解修饰的方法再调用proceed的时候会执行下一个拦截器
4.6 MethodBeforeAdviceInterceptor类
该类是InterceptorAndDynamicMethodMatcher类型的
源码:
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
做了2件事:
1.this.advice.before方法执行@Before前置增强注解的内容。
2.调用proceed方法执行下一个拦截器
我debug的情况是这个拦截器执行完了过后,就执行目标对象的真实方法了。