实现一个拦截器必须要实现一下几个类:
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(“具体方法”)
 
 

最新文章

  1. 使用TabBarController(代码实现)
  2. cocos2dx 3.x以上版本搭建Mac环境(百分百可行)
  3. java 抽象类和接口的区别
  4. Core Java Volume I — 5.1. Classes, Superclasses, and Subclasses
  5. arm-linux-objcopy
  6. 关于Protobuf在游戏开发中的运用
  7. JQuery操作元素的属性与样式及位置 复制代码
  8. Spring Boot 使用 Log4j2
  9. GitHub-创建仓库与本地同步
  10. flask SQLALchemy外键及约束
  11. [转载]linux内存映射mmap原理分析【转】
  12. 把去世的亲友做成聊天机器人,就能让生者慰藉、死者安息吗? - 看了 寻梦历险记,我的回答是 :是的,他/她永远活在我们心里 www.iremember.com.cn
  13. 另一道不知道哪里来的FFT题
  14. 一条命令将windows下多个ts文件合并为一个ts文件
  15. ubuntu 16.04 更换源
  16. 处理 Java Tomcat 的“Cannot allocate memory”错误
  17. 【刷题】洛谷 P1519 穿越栅栏 Overfencing
  18. Windows互斥锁demo和分析
  19. 5W次单点修改,求最长的连续上升子序列 HDU 3308
  20. Spring Boot(一)启动方式

热门文章

  1. window nodejs 版本管理器 nvm-windows 教程
  2. MySql的基操勿六
  3. Linux内核——进程管理之CFS调度器(基于版本4.x)
  4. php-7.0.16 , apache2.4.25 配置
  5. 使用POI循环写入数据时发现只有最后一列有数据
  6. django第四天(路由别名,django2.x新特性和自定义转换器)
  7. 记我的小网站发现的Bug之一 —— 某用户签到了两次
  8. H.264 Profile-level-id
  9. window.close()
  10. python jieba包用法总结