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(“具体方法”)
     
     
  • 相关阅读:
    【Ecstore2.0】计划任务/队列/导入导出 的执行问题
    【Ecstore2.0】第三方信任登陆问题解决_备忘
    Ecstore 2.0 报表显示空白
    【Linux】 任务调度/计划 cron
    wdcp/wdlinux一键包的php5.3版本添加Zend.so 和Soap.so
    wdcp/wdlinux 在 UBUNTU/linux 中安装失败原因之创建用户
    假如女人是一种编程语言,你会更喜欢哪一种
    Linux中的ln
    wdcp/wdlinux 常用工具及命令集
    php 数组Array 删除指定键名值
  • 原文地址:https://www.cnblogs.com/panxuejun/p/7719413.html
Copyright © 2011-2022 走看看