目录
一、前言
通过上一篇 Spring源码学习【六】AOP原理解析(一)代理对象的生成 的学习,我们知道了Spring是通过后置处理器来生成代理对象的,且获取到代理对象后会阻止原Bean的默认实例化行为,从而将代理对象提供给用户使用,并通过代理对象实现对目标对象的增强,有了这些知识储备,我们继续以JdkDynamicAopProxy为例,学习一下代理对象是如何对目标对象进行增强的。
二、源码学习
回到上一篇JdkDynamicAopProxy类中,我们可以发现JdkDynamicAopProxy类实现了InvocationHandler接口,在利用Java反射机制创建代理对象的同时将传入了this对象引用,代码如下:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
...
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
}
这里的InvocationHandler接口是代理对象需要实现的接口,其中定义了Invoke方法,用于以回调的方式拦截目标对象方法的调用,我们可以以JdkDynamicAopProxy为例学习invoke的实现,代码如下:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 目标对象未实现equals方法
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 目标对象未实现hashCode方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// 装饰模式代理
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
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);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 拦截器链空,则直接执行目标对象方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 调用拦截器
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
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);
}
}
}
}
上面的代码中我们需要关注两个方面:其一,目标对象targer的方法调用;其二,拦截器的调用。
首先,看一看目标对象方法的调用,使用了Java的反射机制,具体实现在AopUtils类中,代码如下:
public abstract class AopUtils {
@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable {
// 通过反射调用方法
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
}
然后,看一看拦截器的调用,具体实现在ReflectiveMethodInvocation类中,代码如下:
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
@Override
@Nullable
public Object proceed() throws Throwable {
// index由-1开始调用拦截器,当所有拦截器调用完毕后再调用目标对象的方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 从interceptorsAndDynamicMethodMatchers中获取一个对象
// 这个对象可能是一个匹配器或是一个拦截器
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 取得匹配器则需要对目标方法进行匹配
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
// 匹配成功,调用拦截器
return dm.interceptor.invoke(this);
}
else {
// 匹配失败,跳过该拦截器,进行递归
return proceed();
}
}
else {
// 直接取得了一个拦截器,那么无需匹配直接调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
@Nullable
protected Object invokeJoinpoint() throws Throwable {
// 调用目标对象的方法
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
}
到这里,我们就大体了解了拦截器链和目标方法的调用过程,在我们调用代理对象的目标方法时,会回调到代理对象的invode方法中,在这个方法中调用拦截器链,最终调用目标方法。在这个过程中,我们发现最终调用的拦截器链是由ReflectiveMethodInvocation持有的,拦截器链在构造方法中进行了初始化,如下所示:
protected final List<?> interceptorsAndDynamicMethodMatchers;
/**
* @param proxy 代理对象
* @param target 目标对象
* @param method 目标方法
* @param arguments 目标方法参数
* @param targetClass 目标类
* @param interceptorsAndDynamicMethodMatchers 拦截器链
*/
protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target,
Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass,
List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
经过上一篇的分析,我们知道ReflectiveMethodInvocation是在JdkDynamicAopProxy的invoke方法中构造的,在构造ReflectiveMethodInvocation对象前,先获取了目标方法的拦截器链,代码如下:
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
上面的这句代码十分重要,现在我们知道Spring是通过生成代理类来实现对目标对象的增强的,在执行目标对象的目标方法前,会首先执行代理对象中配置的一系列拦截器,这里便是获取了所有拦截器,接下来看一看具体的代码:
public class AdvisedSupport extends ProxyConfig implements Advised {
/**
* 获取拦截器链,可以看到这里使用了缓存,最终拦截器链的获取由AdvisorChainFactory接口的实现类
* DefaultAdvisorChainFactory实现
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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;
}
}
DefaultAdvisorChainFactory用于为目标方法创建拦截器链,代码如下:
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
/**
* 创建拦截器链
*
*/
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {
// 这里的config实际上之前创建的ProxyFactory,ProxyFactory间接实现了Advised接口
List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
// 取得一个registry,这里使用了单例模式,用于注册通知适配器
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
// 处理切入点通知,方法级别增强
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 通过registry取得拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
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)) {
// 通过registry取得拦截器
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
// 通过registry取得拦截器
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
}
上面的代码中最终返回了一个方法拦截器的列表,在这个过程中,多次调用了AdvisorAdapterRegistry的getInterceptors(advisor)方法,下面深入到AdvisorAdapterRegistry接口的实现类DefaultAdvisorAdapterRegistry中看一看具体实现:
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
/**
* 获取拦截器
*/
@Override
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);
}
for (AdvisorAdapter adapter : this.adapters) {
// 判断通知是否可被适配器理解
// 实际上是对advice类型的判断,如AfterReturningAdvice等
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
/**
* 注册通知适配器
*/
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
到这里,拦截器链就构造完成了,在这个过程中,通过适配器的支持,构造了不同的拦截器,在JdkDynamicAopProxy进行回调时则会根据配置的通知执行相应的拦截器链,从而达到增强目标对象的功能。
Spring的AOP模块是一个复杂的模块,这里仅仅简要分析了通过代理对象增强目标对象的原理和过程,还有更多的知识需要在实践中不断学习。