spring适配器模式-aop中的MethodInterceptor拦截器
AOP(Aspect Orient Programming),一般称为面向方面(切面)编程,作为面向对象的一种补充,
我们将业务处理的主要流程是作为核心关注点,而用于处理系统中分布于各个模块中与核心业务无关的, 比如事务管理、日志、缓存等等,称为横切关注点,AOP的作用就是将核心关注点和横切关注点分离开来。
AOP核心概念
1、切入点(pointcut)
需要要增强的目标方法,比如:你的一个类有很多方法,但是只需要在login方法执行记录一下日志,其他的方法不需要,那么这login方法就是一个切点
2、连接点(joinpoint)
这里指的是方法连接点,连接点可以说是切点的全集。方法有关的前前后后都是连接点。
3、通知(advice)
某个方法在执行前或执行后需要完成的工作,比如在某个方法执行完成后记录一下日志。在什么时候和要完成什么通过方法名中的before,after,around等来实现
4、切面(aspect)
切面是通知和切点的结合,切点和通知共同定义了切面的全部功能——它是什么,在何时何处完成其功能 , 切面就是对横切关注点的抽象
AOP实现的关键在于AOP框架自动创建的AOP代理,
AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改原来原来的对象,而是在需要的时候重新生成一个代理对象,这个代理对象包含了目标对象的全部方法,并且在指定的切点做了了处理,而且最终还是回调原对象的方法。
动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。
如果目标类没有实现接口,那就要选择使用CGLIB来动态代理目标类。
CGLIB会让生成的代理类继承当前对象,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。
在CGLIB底层底层实现是通过ASM字节码处理框架来转换字节码并生成新的代理类
注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
在Spring Aop框架中,MethodInterceptor接口被用来拦截指定的方法,对方法进行增强。
在Aop中每个advistor 里面会有一个advice具体做切面动作,Spring提供了AspectJAfterReturningAdvice,AspectJMethodBeforeAdvice,AspectJAroundAdvice,AspectJAfterAdvice这几个advice,在XML 配置aop时候会指定<aop:after-returning/>,<aop:before/>,<aop:around/>,<aop:after/>
,其实内部就是创建上面对应的这些advice。
从图知道AspectJAfterReturningAdvice和AspectJMethodBeforeAdvice没有实现MethodInterceptor接口,其他两者则实现了该接口。
而Spring Aop的方法拦截器却必须是实现了MethodInterceptor的,所以Spring提供了对应的适配器来适配这个问题,分别是MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter和ThrowsAdviceAdapter。
适配器模式属于结构性模式,它为两个不同接口之间互通提供了一种手段。
下面是 DefaultAdvisorAdapterRegistry类的全部代码, 会默认注册 上面三个适配器,
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
*/
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> 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()]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
以MethodBeforeAdviceAdapter为例子看下:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
MethodBeforeAdviceInterceptor的代码如下:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
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();
}
}
可知MethodBeforeAdviceInterceptor继承了MethodInterceptor作为了一个适配器内部委托请求给MethodBeforeAdvice。