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。

 

posted @ 2018-09-15 21:29  南极山  阅读(11117)  评论(0编辑  收藏  举报