JDK中的Poxy类简单实现动态代理
来源:互联网 发布:南京网络推广江苏斯点 编辑:程序博客网 时间:2024/05/20 16:14
一、类所在位置
Proxy类在java.lang.reflect包下
java.lang.Object java.lang.reflect.Proxy
Serializable
二、该类的主要方法
Object proxyObject = Proxy.newProxyInstance(loader , interfaces, h);
三个参数的意义
1.classLoader 类加载器,将class文件加载到内存中,形成class对象
2.Class[] interfaces 需要实现的接口
3.InvocationHandler 调用处理器,代理对象的所实现的所有接口的方法,内容都是调用InvocationHandler
的invoke()方法
现在写代码测试下这个类,现有接口A,B,动态生成一个类同时实现A和B接口,代码如下
package org.edu.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.junit.Test; public class Demo1 { interface A { void a(); void aa(); } interface B { void b(); void bb(); } @Test public void test1() { /* * 给出三大参数,然后动态生成这个类,这个类实现了提供的接口,然后生成这个类的对象 * 1.classLoader 类加载器 * 2.Class[] interfaces 需要实现的接口 * 3.InvocationHandler 调用处理器,代理对象的所实现的所有接口的方法,内容都是调用InvocationHandler * 的invoke()方法 */ ClassLoader loader = this.getClass().getClassLoader(); Class[] interfaces = {A.class, B.class}; InvocationHandler h = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("你好动态代理"); return null; } }; Object proxyObject = Proxy.newProxyInstance(loader , interfaces, h); A a = (A) proxyObject; a.a(); a.aa(); B b = (B) proxyObject; b.b(); b.bb(); } }
单元测试结果如下
从结果中可以看出两个问题。
1.将代理对象强转成A接口和B接口没有报错,说明生成的代理对象同时实现了A接口和B接口。
2.调用代理对象的a()方法、aa()方法、b(),还有bb()方法,结果都是调用了InvocationHandler的invoke()方法,说明执行代理的对象的方法都是通过执行InvocationHandler的invoke()方法来实现的。
好,这是我们再测试下是不是所有方法都是这样呢?
结果发现,在执行toStirng()方法的时候执行了invoke()
在执行getClass()方法的时候没有执行,在执行hashcoe()方法的时候抛出了异常,这个不知道为什么。看了Object类的源码,发现getClass()方法是final和native修饰的,说明是本地方法,是用底层的c写的,不涉及到java代码,没有被重写。
我们想知道这个类的类型到底是什么,于是加入
System.out.println(a.getClass().getName());
结果是org.edu.proxy.$Proxy4
说明生成的对象的类型是一个代理类,为什么叫这个名字,who konws!
三、InvocationHandler的invoke()方法
public Object invoke(Object proxy, Method method, Object[] args)
Object proxy:代理对象。
Method method:调用的方法
Object[] args:实参,调用接口方法传进来的的参数
Object返回值:接口方法的返回值
四、动态代理的简单实现
动态代理的作用,增强
将原有的对象和需要增强的功能结合成一个代理对象,从而达到增强的效果。
代理对象=目标对象+增强
比如现在我有一个服务员接口,接口有服务方法,一个男服务员继承了这个接口,这个男服务员很呆板,只会服务,现在我需要让他变得礼貌一点,开始说您好,结束时说再见。我该怎么实现呢?
服务员接口
package org.edu.proxy;/** * 服务员类 * @author ZGJ * @date 2016年12月4日 */public interface Waiter {/** * 服务方法 */void serve();}
男服务员类
package org.edu.proxy;/** * 男服务员 * @author ZGJ * @date 2016年12月4日 */public class ManWaiter implements Waiter{@Overridepublic void serve() {// TODO Auto-generated method stubSystem.out.println("服务中......");}}
实现如下
package org.edu.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import org.junit.Test;/** * * @author ZGJ * @date 2016年12月4日 */public class Demo2 {@Testpublic void fun() {ManWaiter manWaiter = new ManWaiter();ClassLoader loader = this.getClass().getClassLoader();Class[] interfaces = {Waiter.class};//传入目标对象InvocationHandler h = new WaiterInvocationHandler(manWaiter);//得到增强的代理对象Waiter waiterProxy = (Waiter) Proxy.newProxyInstance(loader , interfaces, h);//开始时说您好,结束时说再见waiterProxy.serve();}}class WaiterInvocationHandler implements InvocationHandler{private Waiter Waiter;public WaiterInvocationHandler(Waiter waiter) {// TODO Auto-generated constructor stubthis.Waiter = waiter;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubSystem.out.println("您好!");Waiter.serve();System.out.println("再见!");return null;}}
但是,这种方式好像不是特别灵活,因为增强的方式都写死了,不够灵活。
这个时候,就可以使用代理工厂来实现生产代理对象
1.现在写两个接口
BeforeAdvice 前置增强
package org.edu.proxy.demo3;/** * 前置增强 * @author ZGJ * @date 2016年12月4日 */public interface BeforeAdvice {void before();}
AfterAdvice 前置增强
package org.edu.proxy.demo3;/** * 后置增强 * @author ZGJ * @date 2016年12月4日 */public interface AfterAdvice {void after();}
ProxyFactory代理工厂类
package org.edu.proxy.demo3;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 代理工厂类 * @author ZGJ * @date 2016年12月4日 */public class ProxyFactory {private Object target;//目标对象private BeforeAdvice beforeAdvice;//前置增强private AfterAdvice afterAdvice;//后置增强/** * 用来生成代对象 * @return */public Object createProxy() {ClassLoader loader = this.getClass().getClassLoader();Class<?>[] interfaces = target.getClass().getInterfaces();InvocationHandler h = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stub//执行前置增强if(beforeAdvice != null) {beforeAdvice.before();}//调用目标方法Object result = method.invoke(target, args);//执行后置增强if(afterAdvice != null) {afterAdvice.after();}return result;}};/* * 三大参数 */Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);return proxyObject;}public Object getTarget() {return target;}public void setTarget(Object target) {this.target = target;}public BeforeAdvice getBeforeAdvice() {return beforeAdvice;}public void setBeforeAdvice(BeforeAdvice beforeAdvice) {this.beforeAdvice = beforeAdvice;}public AfterAdvice getAfterAdvice() {return afterAdvice;}public void setAfterAdvice(AfterAdvice afterAdvice) {this.afterAdvice = afterAdvice;}}
Demo3实现了目标对象和增强都可以切换
package org.edu.proxy.demo3;import org.junit.Test;/** * 目标对象和增强都可以切换的动态代理 * @author ZGJ * @date 2016年12月4日 */public class Demo3 {@Testpublic void fun() {Waiter waiter = new ManWaiter();ProxyFactory factory = new ProxyFactory();//创建工厂factory.setTarget(waiter);//设置目标对象factory.setBeforeAdvice(new BeforeAdvice() {@Overridepublic void before() {// TODO Auto-generated method stubSystem.out.println("您好");}});factory.setAfterAdvice(new AfterAdvice() {@Overridepublic void after() {// TODO Auto-generated method stubSystem.out.println("再见");}});Waiter waiterProxy = (Waiter) factory.createProxy();waiterProxy.serve();}}
如果我想修改前置增强的方法,只需新建一个类继承前置增强的接口就行了,后置增强同理,被增强的目标对象也可以切换,这样就灵活很多了。
1 0
- JDK中的Poxy类简单实现动态代理
- Poxy代理类
- Jdk动态代理简单实现
- 简单的 JDK实现动态代理
- JDK动态代理实现简单AOP--转
- 简单的Jdk动态代理实现:
- 粗略实现jdk中的接口动态代理
- JDK中的动态代理
- JDK中的动态代理
- JDK中的动态代理
- JDK中的动态代理
- jdk中的动态代理
- JDK中的动态代理
- JDK中的动态代理
- JDK中的动态代理
- AOP实现--JDK中的动态代理和cglib代理
- JDK动态代理实现
- jdk动态代理实现
- hdu 1248 寒冰王座(完全背包)
- [C++]C++中的虚函数
- 分布式一致性原理、Paxos算法与Zookeeper的ZAB协议、Zookeeper使用场景与在电商系统中的应用
- MySql_安装
- 对某音乐网站歌曲链接抓取的分析
- JDK中的Poxy类简单实现动态代理
- <<Linux内核完全剖析 --基于0.12内核>>学习笔记 第4章 80x86保护模式及其编程 4.4 分页机制
- Markdown
- hdu 1175 连连看
- Xcode基本操作
- Android MVP模式的简单实现
- 重写系统返回键
- Android文件共享之检索文件信息
- 1