AOP原理(二):AopProxy拦截机制

以JDK动态代理为例,看一下Aop代理的拦截机制:

JdkDynamicAopProxy的invoke拦截

使用JDK动态代理生成代理对象时,需要传入三个参数,分别是目标对象的类加载器loader、目标对象的接口interfaces、一个InvocationHandler对象:

1
2
3
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)

InvocationHandler是一个接口,定义了一个invoke方法,对目标对象方法调用的拦截就是在invoke方法中实现的。

1
2
3
4
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}

JdkDynamicAopProxy

1.拦截器链的调用

JdkDynamicAopProxy实现了InvocationHandler接口,因此生成代理对象时,可以将自身作为参数传入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//使用JDK动态代理生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

/**
* InvocationHandler接口invoke方法的实现
*/
@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)) {
// 如果目标对象没有实现Object的equals方法
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 目标对象没有实现hashcode方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
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) {
// Make invocation available if necessary.
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 {
//创建一个ReflectiveMethodInvocation对象,调用拦截器之后再调用目标对象的方法
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()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}

(1)在invoke方法中,如果没有配置拦截器,将会通过AopUtils的invokeJoinpointUsingReflection方法,使用反射机制对目标对象的方法进行调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
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);
}
}
}

(2)如果配置了拦截器,会获创建一个ReflectiveMethodInvocation对象,通过ReflectiveMethodInvocation对象的proceed方法逐个运行拦截器的拦截方法,从而完成整个拦截器链的调用。当拦截器链执行完毕后,同样使用反射机制执行目标对象中的方法。
在运行拦截器的拦截方法之前,会进行动态匹配判断,判断是否和定义的pointcut匹配,如果匹配就会执行这个advice。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
@Override
@Nullable
public Object proceed() throws Throwable {
// 如果拦截器链调用完毕
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//这里依旧使用AopUtils的invokeJoinpointUsingReflection方法使用反射机制完成目标对象方法的调用
return invokeJoinpoint();
}
//获取定义的拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果是InterceptorAndDynamicMethodMatcher的实例
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 对拦截器进行动态匹配判断,如果和定义的切点匹配,将会执行这个advice
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);
}
}

2.配置通知器

回到JdkDynamicAopProxy的ivoke方法中,有一个获取当前方法的拦截器链的过程:

1
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

getInterceptorsAndDynamicInterceptionAdvice方法是在AdvisedSupport类中实现的,在这个方法中,还使用到了缓存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class AdvisedSupport extends ProxyConfig implements Advised {
/**
* 从配置中获取拦截器
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
//使用了缓存
MethodCacheKey cacheKey = new MethodCacheKey(method);
//从缓存中获取拦截器
List<Object> cached = this.methodCache.get(cacheKey);
//如果缓存中不存在
if (cached == null) {
// 使用advisorChainFactory获取拦截器链
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
}

如果缓存中不存在拦截器链,会调用AdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法获取拦截器链,AdvisorChainFactory是一个生产通知器链的工厂:

1
2
3
4
public interface AdvisorChainFactory {
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);

}

AdvisorChainFactory是一个接口,它的子类DefaultAdvisorChainFactory实现了该方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {

// 根据配置中通知器的个数设置list的长度
List<Object> interceptorList = new ArrayList<>(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)) {
//通知器转为对应的拦截器
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)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}

return interceptorList;
}
}

来看这行代码,从GlobalAdvisorAdapterRegistry类中获取了通知适配器注册实例AdvisorAdapterRegistry:

1
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
GlobalAdvisorAdapterRegistry

GlobalAdvisorAdapterRegistry是一个抽象类,返回的是一个单例模式的DefaultAdvisorAdapterRegistry对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class GlobalAdvisorAdapterRegistry {

/**
* 单例模式,使用了DefaultAdvisorAdapterRegistry实现
*/
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();

/**
* 返回实例
*/
public static AdvisorAdapterRegistry getInstance() {
return instance;
}

/**
* 重置
*/
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}

}

DefaultAdvisorAdapterRegistry

DefaultAdvisorAdapterRegistry在构造方法中注册了一系列的适配器,在getInterceptors方法中通过适配器模式完成了advice向拦截器的转换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}

/**
* 获取拦截器
*/
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
//创建一个list,存放的类型是MethodInterceptor
List<MethodInterceptor> interceptors = new ArrayList<>(3);
//从Advisor通知器配置中获取advice通知
Advice advice = advisor.getAdvice();
//如果是MethodInterceptor类型的,不需要适配器,直接加入拦截器集合中
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
//这里判断取得的advice是什么类型的通知器,从而注册不同的拦截器
if (adapter.supportsAdvice(advice)) {
//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);
}

}

getInterceptors方法中,传入的参数是Advisor类型的通知,返回的是方法拦截器集合,每个通知器都有对应的方法拦截器,比如BeforeAdvice通知器的拦截器是MethodBeforeAdviceInterceptor,该方法的作用就是通过适配器模式将通知器转为对应的方法拦截器。所以通知器如果是MethodInterceptor类型的直接加入集合,如果不是,需要通过适配器模式将通知转为拦截器:

1
2
3
4
5
6
7
for (AdvisorAdapter adapter : this.adapters) {
//这里判断取得的advice是什么类型的通知器,从而注册不同的拦截器
if (adapter.supportsAdvice(advice)) {
//通过适配器模式advice转为拦截器加入到集合
interceptors.add(adapter.getInterceptor(advisor));
}
}

Spring AOP适配器模式的应用

1.AdvisorAdapter

上面知道通过调用AdvisorAdapter的getInterceptor方法将通知器advisor转为了对应的拦截器MethodInterceptor,AdvisorAdapter是一个接口,定义了两个方法,分别是
supportsAdvice和getInterceptor:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface AdvisorAdapter {

/**
* 判断通知器的类型是否支持
*/
boolean supportsAdvice(Advice advice);

/**
* advisor转为MethodInterceptor
*/
MethodInterceptor getInterceptor(Advisor advisor);

}
MethodInterceptor
1
2
3
4
5
6
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {

Object invoke(MethodInvocation invocation) throws Throwable;

}
2.MethodBeforeAdviceAdapter

以MethodBeforeAdviceAdapter为例看一下如何转换的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

@Override
public boolean supportsAdvice(Advice advice) {
//判断通知器是否是MethodBeforeAdvice的实例
return (advice instanceof MethodBeforeAdvice);
}

@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
//通知器转为MethodBeforeAdvice类型
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
//MethodBeforeAdvice转为MethodBeforeAdviceInterceptor类型
return new MethodBeforeAdviceInterceptor(advice);
}

}
MethodBeforeAdviceInterceptor

MethodBeforeAdviceInterceptor实现了MethodInterceptor接口,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

private MethodBeforeAdvice advice;


/**
* 构造函数
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}

/**
* 拦截器的回调方法,会在代理对象的方法被调用前调用
*/
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}

}

参考:

spring技术内幕:深入解析spring架构与设计原理

jzq114:AOP源码分析之初始化通知器链

峰峰峰峰峰:一起学设计模式 - 适配器模式

Spring版本:5.0.5