为什么需要适配器模式
适配器模式能使接口不兼容的对象能够相互合作,将一个类的接口,转换成客户期望的另外一个接口。
在SpringAOP中有一个很重要的功能就是使用的 Advice(通知)来【增强】【被代理类】的功能,那么通知主要有三种
1、MethodBeforeAdvice
2、AfterReturningAdvice
3、ThrowsAdvice
每个Advice都有对应的拦截器,如下所示:
1、每一种通知,其实是有一个对应的拦截器,那么当目标方法被执行的时候,就会进到这个拦截器,在拦截里面会判断,当前目标类有哪些通知,这样就有哪些拦截器需要执行
2、Spring需要将每个Advice生成对应的拦截器返回给容器,所以需要使用适配器模式对Advice进行转换。对应的就有三个适配器,我们看个类图:
更具上面的情况我们需要用到几个东西,适配器、Advice类型以及Advice类型所对应的拦截器
1、适配器
适配器在Spring中是怎么把通知类和拦截类进行转换的呢,我们先看适配器的接口。定义了两个方法,分别是supportsAdvice()和getInterceptor()。
public interface AdvisorAdapter {
//判断通知类是否匹配
boolean supportsAdvice(Advice advice);
//传入通知类,返回对应的拦截类
MethodInterceptor getInterceptor(Advisor advisor);
}
其实很简单,可以看出转换的方法就是getInterceptor(),通过supportsAdvice()进行判断
我们看前置通知的适配器的实现类MethodBeforeAdviceAdapter。
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
//判断是否匹配MethodBeforeAdvice通知类
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
//传入MethodBeforeAdvice,转换为MethodBeforeAdviceInterceptor拦截类
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
getInterceptor()方法中,调用了对应的拦截类的构造器创建对应的拦截器返回,传入通知类advice作为参数。接着我们看拦截器MethodBeforeAdviceInterceptor。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
//成员变量,通知类
private MethodBeforeAdvice advice;
//定义了有参构造器,外部通过有参构造器创建MethodBeforeAdviceInterceptor
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
//当调用拦截器的invoke方法时,就调用通知类的before()方法,实现前置通知
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//调用通知类的before()方法,实现前置通知
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
那么在哪里初始化这些适配器呢,或者这些拦截器是怎么被处理的,我们看DefaultAdvisorAdapterRegistry()
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
//将Advisor转成拦截器,存到该变量中
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
public DefaultAdvisorAdapterRegistry() {
//初始化适配器,添加到adapters集合,也就是注册
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
//获取所有的拦截器
@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);
}
//遍历adapters集合
for (AdvisorAdapter adapter : this.adapters) {
//调用supportsAdvice()方法,判断入参的advisor是否有匹配的适配器
if (adapter.supportsAdvice(advice)) {
//如果匹配,则调用getInterceptor()转换成对应的拦截器,添加到interceptors集合中
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
//返回拦截器集合
return interceptors.toArray(new MethodInterceptor[0]);
}
}
适配器模式在这里就是把通知类转为拦截器类,转为拦截类之后,就添加到拦截器集合中。添加到拦截器集合之后,就用到了责任链模式,在ReflectiveMethodInvocation类被调用,我们看JDK动态代理JdkDynamicAopProxy的invoke()方法。
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
//这里就是获取拦截器集合,最后就会调用到上文说的getInterceptors()
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
//省略...
}else {
//创建一个MethodInvocation
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//调用proceed()方法,底层会通过指针遍历拦截器集合,然后实现前置通知等功能
retVal = invocation.proceed();
}
//省略...
}
最后就在ReflectiveMethodInvocation里调用proceed()方法,proceed()方法是一个递归的方法,通过指针控制递归的结束。这是很典型的责任链模式。
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
protected final List<?> interceptorsAndDynamicMethodMatchers;
//指针
private int currentInterceptorIndex = -1;
protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
//省略...
//拦截器的集合
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//递归结束
return invokeJoinpoint();
}
//获取拦截器,并且当前的指针+1
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 {
//匹配拦截器,强转为拦截器,然后执行invoke()方法,然后就会调用拦截器里的成员变量的before(),afterReturning()等等,实现前置通知,后置通知,异常通知
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
}
这里可能没学过责任链模式的同学会看得有点晕,但是学过责任链模式应该很容易看懂,这其实跟SpringMVC的拦截器的逻辑实现几乎一样的。