Spring源码解析 -- 读取bean元数据
spring源码解析 -- 构造bean
spring源码解析 -- 注入属性
spring源码解析 -- Spring Context
Spring源码解析 -- AOP原理(1)
Spring源码解析 -- AOP原理(2)
Spring源码解析 -- SpringMvc原理
源码分析基于spring 4.3.x
本文承接上一篇文章对Spring AOP的分析,继续分析spring如何对AOP中多个通知进行链式调用的。
关于阅读源码的思路,可参考 -- 如何阅读java源码
《Spring源码解析 -- AOP原理(1)》 中说了,JdkDynamicAopProxy实现了InvocationHandler,正是这个类调用AOP通知中定义的增强方法。
JdkDynamicAopProxy#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 {
... // #1
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // #2
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); // #3
}
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // #4
retVal = invocation.proceed(); // #5
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // #6
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()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
#1
处理equals/hashCode等方法,直接调用目标方法#2
getInterceptorsAndDynamicInterceptionAdvice -- 获取方法拦截器#3
没有方法拦截器,直接调用目标方法#4
构造调用链ReflectiveMethodInvocation#5
调用调用链#6
处理特殊场景 -- 方法返回值为this
AdvisedSupport#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();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { // #1
MethodInterceptor[] interceptors = registry.getInterceptors(advisor); // #2
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { // #3
if (mm.isRuntime()) { // #4
// 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)); // #5
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors)); // #6
}
}
}
}
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;
}
#1
判断class是否匹配pointcut#2
getInterceptors -- 将advisor转化为MethodInterceptor方法拦截器,MethodInterceptor#invoke负责调用被拦截的方法#3
判断method是否匹配pointcut#4
是否运行时判断#5
添加InterceptorAndDynamicMethodMatcher到结果#6
添加MethodInterceptor到结果
DefaultAdvisorAdapterRegistry#getInterceptors:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
有三个Advice没有实现MethodInterceptor,通过DefaultAdvisorAdapterRegistry#adapters适配
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
回到JdkDynamicAopProxy#invoke方法#5
步骤,调用调用链
ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { // #1
return invokeJoinpoint(); // #2
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //#3
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { //#4
...
}
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); //#5
}
}
#1
判断是否到拦截器链末尾,注意currentInterceptorIndex初始值是-1#2
拦截器已经调用完,调用被拦截的方法#3
获取下一个拦截器#4
是否为需要运行时判断#5
直接调用拦截器
调用链ReflectiveMethodInvocation中的节点是拦截器MethodInterceptor。
ReflectiveMethodInvocation#proceed方法会获取下一个拦截器,并调用MethodInterceptor#invoke方法。
注意,调用拦截器MethodInterceptor#invoke方法时会将调用链ReflectiveMethodInvocation作为参数,拦截器MethodInterceptor#invoke执行完逻辑后,又调用ReflectiveMethodInvocation#proceed,继续调用下一个拦截器。
看看AspectJAroundAdvice的实现
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi; // #1
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi); // #2
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null); // #3
}
#1
获取调用链#2
使用调用链构造一个MethodInvocationProceedingJoinPoint#3
调用增强方法
protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t)); // #1
}
#1
invokeAdviceMethodWithGivenArgs -- 通过反射调用增强方法,就是执行Around通知
argBinding -- 负责参数绑定
AbstractAspectJAdvice#argBinding
protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable ex) {
calculateArgumentBindings(); //#1
// AMC start
Object[] adviceInvocationArgs = new Object[this.parameterTypes.length];
int numBound = 0;
if (this.joinPointArgumentIndex != -1) { //#2
adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
numBound++;
}
else if (this.joinPointStaticPartArgumentIndex != -1) {
adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();
numBound++;
}
if (!CollectionUtils.isEmpty(this.argumentBindings)) { //#3
// binding from pointcut match
if (jpMatch != null) {
PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();
for (PointcutParameter parameter : parameterBindings) {
String name = parameter.getName();
Integer index = this.argumentBindings.get(name);
adviceInvocationArgs[index] = parameter.getBinding();
numBound++;
}
}
// binding from returning clause
if (this.returningName != null) {
Integer index = this.argumentBindings.get(this.returningName);
adviceInvocationArgs[index] = returnValue;
numBound++;
}
// binding from thrown exception
if (this.throwingName != null) {
Integer index = this.argumentBindings.get(this.throwingName);
adviceInvocationArgs[index] = ex;
numBound++;
}
}
if (numBound != this.parameterTypes.length) {
throw new IllegalStateException("Required to bind " + this.parameterTypes.length +
" arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
}
return adviceInvocationArgs;
}
#1
通过反射获取参数名,返回名等信息,设置joinPointArgumentIndex,argumentBindings等属性#2
添加JoinPointMatch到增强方法的参数中#3
添加被拦截方法参数,返回值,异常等数据到增强方法的参数中
在环绕通知中,我们需要编写如下代码
@Around("...")
public Object methodAroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = joinPoint.proceed(joinPoint.getArgs());
return result;
}
这里joinPoint.proceed(joinPoint.getArgs());
调用了下一个拦截器(MethodInvocationProceedingJoinPoint#proceed会调用ReflectiveMethodInvocation#proceed),这样才能继续调用拦截器调用链。
@Before通知会调用MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); // #1
return mi.proceed(); // #2
}
#1
执行@Before增强#2
继续拦截器调用链
@After通知会调用AspectJAfterThrowingAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed(); // #1
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex); // #2
}
throw ex;
}
}
#1
先调用拦截器链#2
执行@After增强
到这里,spring aop的源码解析就完成了。
这部分还是挺复杂的,需要耐心点看源码。
如果您觉得本文不错,欢迎关注我的微信公众号,您的关注是我坚持的动力!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。