实现一个拦截器必须要实现一下几个类:
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");
}
}
3 拦截器类:目标类中的方法被拦截之后,执行拦截器中的方法。
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(“具体方法”)
- 一个例子让你了解Java反射机制
本文来自:blog.csdn.net/ljphhj JAVA反射机制: 通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运 ...
- (转)个例子让你了解Java反射机制
个例子让你了解Java反射机制 原文地址:http://blog.csdn.net/ljphhj/article/details/12858767 JAVA反射机制: 通俗地说,反射机制就是可 ...
- (转)JAVA反射机制理解
JAVA反射机制: 通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没 ...
- 【java提高】---java反射机制
java反射机制 一.概述 1.什么是反射机制 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态 ...
- Java中过滤器和拦截器的区别
1.拦截器是基于java反射机制的,而过滤器是基于函数回调的. 2.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器. 3.拦截器只对action起作用,而过滤器几乎可以对所有请求起 ...
- 第28章 java反射机制
java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...
- java基础知识(十一)java反射机制(上)
java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...
- java基础知识(十一)java反射机制(下)
1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...
- Java反射机制专题
·Java Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方 ...
随机推荐
- 268. Missing Number@python
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missin ...
- MySQL中常见的锁
一.按读写方式分类 1.读锁又称共享锁,读锁是共享的,读锁之间是互不阻塞. 2.写锁又称排他锁,写锁是排他的,写锁会阻塞其他读锁和写锁 二.按锁的粒度分类 1.表锁是MySQL中最基本的锁策略,该锁的 ...
- 【php】类型转换
$a = 9; print_r((array) $a) ; 输出: [0=>9] print_r((array) null); 输出: []
- XML,面向对象基础
什么是XML XML与JSON的对比 XML文档格式 使用XML模块解析 一,什么是XML ''' XML 全称可扩展标记语言 <tag></tag> 双标签 <tag/ ...
- C++中四种强制类型转换方式
类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比 ...
- http过程
当在浏览器里输入URL地址时,http的通讯过程: 1) 连接 DNS解析:URL——>DNS服务器(找到返回其ip,否则继续将DNS解析请求传给上级DNS服务器) Socket连接:通过IP和 ...
- DRF filter
filter 配置 fiter定义 自定义filter继承BaseFilterBackend,必须重写filter_queryset,返回值为过滤后的queryset filter在GenericAP ...
- [android开发篇]java环境配置
http://www.runoob.com/java/java-environment-setup.html Java 开发环境配置 在本章节中我们将为大家介绍如何搭建Java开发环境. window ...
- 2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)
先把代码扔上来 E. Field of Wonders time limit per test 3 seconds memory limit per test 256 megabytes input ...
- Ubuntu Flask安装与配置(待整理)
工作中开发需要用到python的flask框架,无奈网络上的资源很少,连基本的安装和配置都不全,在这做一下整理,方便以后用到. ———————————————————————————— 由于比较繁琐, ...