zoukankan      html  css  js  c++  java
  • java拦截器中使用的动态代理

    java中拦截器内部实际上是通过jdk动态代理实现的

    拦截器一般至少有三个方法:before, around, after,用来处理拦截方法的前后逻辑,具体逻辑图如下:

    1. 定义拦截器:

    /**
     * 定义拦截器接口
     */
    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);
    }
    
    public class MyInterceptor implements Interceptor {
    
        @Override
        public boolean before(Object proxy, Object target, Method method, Object[] args) {
            System.err.println("反射方法前逻辑");
            return false;
        }
    
        @Override
        public void around(Object proxy, Object target, Method method, Object[] args) {
            System.err.println("取代了被代理的方法");
        }
    
        @Override
        public void after(Object proxy, Object target, Method method, Object[] args) {
            System.err.println("反射方法后逻辑");
        }
    }

    2. 在JDK动态代理中使用拦截器

    定义一个动态代理类,组合进来拦截器,在invoke方法中实现拦截器逻辑

    public class InterceptorJdkProxy implements InvocationHandler {
    
        private Object target;
        private String interceptorClass = null;  //通过拦截器类名引入  
    
        public InterceptorJdkProxy(Object target, String interceptorClass) {
            this.interceptorClass = interceptorClass;
            this.target = target;
        }
    
        public static Object bind(Object target, String interceptorClass) {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorJdkProxy(target, interceptorClass));
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 标识未设置拦截器,可以直接调用原方法返回
            if(interceptorClass == null){
                return method.invoke(target, args);
            }
            Object result = null;
            // 类名反射生成拦截器对象
            Interceptor interceptor = (MyInterceptor)Class.forName(interceptorClass).newInstance();
            if (interceptor.before(proxy, target, method, args)) {
                result = method.invoke(target, args);
            } else {
                interceptor.around(proxy, target, method, args);
            }
            interceptor.after(proxy, target, method, args);
            return result;
        }
    }

     真正在invoke方法中实现拦截器的逻辑,内部都是调用了各种反射机制

    测试:

    public interface HelloWorld{
        public void sayHelloWorld();
    }
    
    class HelloWorldImp implements HelloWorld{
        @Override
        public void sayHelloWorld(){
            System.out.println("Hello World!");
        }
    }
    
    // ------------------
    
    public class InterceptorTest {
        public static void main(String[] args) {
            HelloWorld hwProxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImp(), MyInterceptor.class.getName());
            hwProxy.sayHelloWorld();
        }
    }

    输出:

     反射方法前逻辑
    取代了被代理的方法
    反射方法后逻辑

  • 相关阅读:
    Linux:删除程序
    Linux:目录操作
    Linux:加载硬盘
    mysql:查询结果添加序列号
    mysql:结果集去重
    mysql:字符串转换为日期类型
    MVC:上传文件时限制文件类型
    WebApi:WebApi的Self Host模式
    WebApi:过滤器的种类
    几种知名开源富文本编辑器记录和对比(仅供参考)
  • 原文地址:https://www.cnblogs.com/alison-lxj/p/11094126.html
Copyright © 2011-2022 走看看