一、简要介绍

       在java中有多种动态代理技术,比如JDK、CGLIB、ASM、javassist,其中最常用的动态代理技术有两种:一种是JDK动态代理,这是JDK自带的功能;另一种是CGLIB,这是第三方提供的一个技术。JDK动态代理&CGLIB(Code Generator Library,是一个强大的、高性能的代码生成库)动态代理。
     JDK动态代理是java.lang.reflect.*包提供的方式,它必须借助一个接口才能产生代理对象。由于动态代理一般比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只需要知道拦截器接口的方法、含义和作用即可,无须知道动态代理是怎么实现的。

        二、实现过程

1、目标接口及实现类:HelloWorld、HelloWorldImp,拦截器会对改业务进行拦截

public interface HelloWorld {
     public abstract void sayHelloWorld();}
public class HelloWorldImp implements HelloWorld{
     @Override
     public void sayHelloWorld() {
         System.out.println("hello");
     }    }

2、定义拦截器接口:Interceptor

public interface Interceptor {
     public boolean before(Object proxy,Object target,Method method,Object[]args);
     public void around(Object proxy,Object target,Method method,Object[]args);
     public void after(Object proxy,Object target,Method method,Object[]args);
 }1)三个方法参数:proxy代理对象、target真实对象、method方法、args运行方法参数
 2)before方法返回Boolean值,它在真实对象前调用。当为true时反射真实对象的方法;当返回false时,则调用around方法。
 3)在before方法返回为false的情况下,调用around方法。
 4)在反射真实对象方法或者around方法执行之后,调用after方法。

3、Interceptor接口实现类:MyInterceptor

public class MyInterceptor implements Interceptor{
     
     @Override
     public boolean before(Object proxy,Object target,Method method,Object[]args) {
         System.out.println("反射方法前逻辑");
         return false;//不反射被代理对象原有方法
     }
     @Override
     public void after(Object proxy,Object target,Method method,Object[]args) {
         System.out.println("反射方法后逻辑");
     }
     @Override
     public void around(Object proxy,Object target,Method method,Object[]args) {
         System.out.println("取代了被代理对象的方法");
     } 
 }

4、在JDK动态代理中使用拦截器:InterceptorJdkProxy

public class InterceptorJdkProxy implements InvocationHandler{
     
     private Object target;//真实对象
     private String interceptorClass=null;//拦截器全限定名
     
     public InterceptorJdkProxy(Object target,String interceptorClass) {
         this.target=target;
         this.interceptorClass=interceptorClass;
     }
     
     /**
      * 绑定委托对象并返回一个【代理占位】
      * @param target真实对象
      * @return 代理对象【占位】
      * 
      */
     public static Object bind(Object target,String interceptorClass) {
         //取得代理对象,代理对象和真实对象产生关联
         return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorJdkProxy(target, interceptorClass));
     }
     
     @Override
     /*
      * 通过代理对象调用方法,首先进入这个方法
      * @param proxy 代理对象
      * @param method 方法,被调用方法
      * @param args 方法的参数
      * 
      */
     public Object invoke(Object proxy,Method method,Object[]args) throws Throwable {
         if (interceptorClass==null) {
             //没有设置拦截器则直接反射原有方法
             return method.invoke(target, args);
         }
         Object result=null;
         //通过反射生成拦截器
         Interceptor interceptor=(Interceptor)Class.forName(interceptorClass).newInstance();
         //调用前设置方法
         if(interceptor.before(proxy, args, method, args)) {
             //反射原有对象方法
             result=method.invoke(target, args);
         }else {//返回false执行around方法
             interceptor.around(proxy, args, method, args);
         }
         //调用后置方法
         interceptor.after(proxy, args, method, args);
         return result;
     }}

5、测试:MyInterceptorTest

public class MyInterceptorTest {
     public static void main(String[] args) {
         HelloWorld proxy=(HelloWorld)InterceptorJdkProxy.bind(new HelloWorldImp(), "test.MyInterceptor");
         proxy.sayHelloWorld();
     }}

查看测试结果:

java 拦截器 response_ide

6、拦截器工作流程:

java 拦截器 response_拦截器_02