zoukankan      html  css  js  c++  java
  • ,java反射机制实现拦截器

    实现一个拦截器必须要实现一下几个类:
    1 目标类接口:目标类要实现的接口。
    package com.lanvis.reflect;
    public interface ITarget {
        public void doSthing();
        public void doOthing();
    }
    2 目标类:目标类是要被拦截的类。它实现了目标类接口。
    package com.lanvis.reflect;
    public class Target implements ITarget {
        public void doOthing() {
            System.out.println("doOthing");
        }
        public void doSthing() {
            System.out.println("doSthing");
        }
    }
    拦截器类:目标类中的方法被拦截之后,执行拦截器中的方法。
    package com.lanvis.reflect;
    public class Interceptor {
        public void before(){
            System.out.println("before");
        }
        public void after(){
            System.out.println("after");
        }
    }
    4 处理器类:正是处理器把拦截器和目标类耦合在一起。
    package com.lanvis.reflect;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class MyHandler implements InvocationHandler{
        private Object object;
        private Interceptor interceptor=new Interceptor();
        public void setObject(Object object) {
            this.object = object;
        }
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            Object result=null;    
            interceptor.before();
            result=method.invoke(object, args);
            interceptor.after();
            return result;
        }
    }
    5 代理类:程序执行时真正执行的是代理类,代理类是实现了拦截器的流程的类。
    package com.lanvis.reflect;
    import java.lang.reflect.Proxy;
    public class MyProxy {
        public Object getProxy(Object object) {
            MyHandler myHandler = new MyHandler();
            myHandler.setObject(object);
            return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                    object.getClass().getInterfaces(), myHandler);
        }
    }
    6 测试类:用来测试拦截器成功与否。
    package com.lanvis.reflect;
    public class Test {
        public static void main(String[] args){
            ITarget target=new Target();
            MyProxy myProxy=new MyProxy();
            ITarget proxy=(ITarget)myProxy.getProxy(target);
            proxy.doSthing();
            proxy.doOthing();
        }
    }
     
    注:认真学习java反射机制,这很重要。
     
     
    总结:
    JAVA动态代理,调用的是代理类,所以这就需要代理类知道原始目标类有哪些接口啊,这样才能不会调错哈,原始信息都有。
    那怎么才能让代理类知道原始目标类有哪些接口呢?这就需要在创建代理类的时候指定原始目标类的class信息,包括有原始目标class.getInterfaces(),原始ClassLoader,当做参数传进去代理类的构造函数中啊,即
    Proxy.newProxyInstance(object.getClass().getClassLoader(),
                    object.getClass().getInterfaces(), myHandler);
    那么代理类内部怎么实现调用原始目标类呢?通过invocationHandler接口啊,这个接口通过proxy代理类传进来的method实例,(proxy有原始目标类的所有method实例),然后用method实例反射功能去调用原始目标类的自己的方法,传入参数也会跟着proxy的传入参数传进来这个invoke参数里面。所以这就有了最核心的代理类调用原始目标类,代理类实现了调用原始目标类。
     
    那下一步是怎么实现前后拦截的呢?
    :我们都知道是invoke()接口实现的调用原始目标类,最核心的method.invoke()前后就可以啊,前后手动加上要添加的方法。就可以了嘛。
    如:
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            Object result=null;    
            interceptor.before();
            result=method.invoke(object, args);
            interceptor.after();
            return result;
        }
    就实现了利用JDK动态代理AOP面向切面编程,
     
    3.那怎么实现只针对某个接口里的某个方法拦截,而不是针对接口里所有方法都拦截呢?
    :只需要在调用invoke方法里,method调用前,加个if判断嘛,根据method,getName().equal(“具体方法”)
     
     
  • 相关阅读:
    在Exchange 2013中重置用户密码
    在exchange邮箱服务器上启用反垃圾邮件功能
    EMC队列 发件人为空 From Address: <>
    zabbix删除历史记录
    ESXi 6.7 CVE-2018-3646警告的处理
    CentOS安装nmap端口查看工具
    webpack学习
    vscode 点滴
    chrome点滴
    前端资料汇总
  • 原文地址:https://www.cnblogs.com/panxuejun/p/7719413.html
Copyright © 2011-2022 走看看