Spring学习笔记:拦截器

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sinat_38393872/article/details/100562960

这片文章是对自己学习的总结,学习材料是Java EE互联网轻量级框架整合开发 SSM框架(Spring MVC + Spring + Mybatis)和Redis实现。作者是杨开振,周吉文,梁华辉和谭茂华。电子工业出版社出版。

拦截器很容器理解,它就是定义一些方法before,around,after等,然后这些方法,用代理的形式和其它的方法结合,比如和方法a结合。之后每次通过代理调用a方法的话,a方法的执行流程就变成下面流程图所展示的。

这就相当于执行a()进行拦截,然后添加一些操作后再让a()方法继续运行。另外,这里只是举一个例子,并不是说Java里所有的拦截器都是这样的逻辑。这个例子只是想说明什么是拦截器,具体的拦截器的逻辑和这个可能不太一样。总之,拦截器就是通过代理调用一个方法a()后,方法a()的实际执行逻辑可能会多出或减少一些操作,而且拦截器的引入不会改变a()方法原本的代码。

拦截器的实现是通过动态代理技术实现的,有关动态代理技术可以看这篇文章,对动态代理不熟悉的,最好先熟悉相关知识再来看本文章。

了解动态代理技术的话,实现拦截器就很简单了。下面使用JDK动态代理技术实现拦截器。

先定义一个接口,该接口规定a()方法(为了用JDK动态代理,所以要先定义接口)。

public interface Test {
    public void a();
}

然后定义一个类实现这个接口

public class TestImpl implements Test {
    @Override
    public void a() {
        System.out.println("a方法执行了");
    }
}

然后定义before,after等方法

public class Interceptor {
    public boolean before();
    public void around();
    public void after();
}


public class InterceptorImpl implements Interceptor {
    public boolean before() {
        System.out.println("before方法执行了");
        return false;
    }

    public void around() {
        System.out.println("around方法执行了");
    }

    public void after() {
        System.out.println("after方法执行了");
    }
}

现在开始定义代理类

public class InterceptorProxy implements InvocationHandler {
    private Object target = null;
    private Interceptor interceptor = null;

    public Object bind(Object target, Interceptor interceptor){
        this.target = target;
        this.interceptor = interceptor;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj = null;
        if(interceptor.before()){
            obj = method.invoke(target, args);
        }   else{
            interceptor.around();
        }
        interceptor.after();
        return obj;
    }
}

然后执行代理看看输出结果

public class Main {
    public static void main(String[] args) {
        InterceptorProxy interceptorProxy = new InterceptorProxy();
        Test proxy = (Test) interceptorProxy.bind(new TestImpl(), new InterceptorImpl());
        proxy.a();
    }
}

这样写起来好像是在重复动态代理的内容,没什么新意。但是在实际应用中,拦截器的开发和使用是由两个不同的角色完成的。比如以上的代码,开发拦截器的人员只需要对外暴露Interceptor接口,然后调用者就可以覆写其中的before,after,around的方法,然后在调用Main函数中的固定代码块,就能实现拦截器的功能,即使调用者对动态代理一窍不通。

所以,拦截器的意义,其实是为了方便调用者更简单地实现动态代理技术。

理解了拦截器之后,对Spring中的AOP编程思想的理解便水到渠成。

猜你喜欢

转载自blog.csdn.net/sinat_38393872/article/details/100562960