java动态代理

来源:互联网 发布:java 策略模式应用 编辑:程序博客网 时间:2024/05/20 23:37

1. 动态代理是什么?

    代理:A需要访问C,但是A又不能或不想直接访问C,如果说A可以通过B来访问C,此时B就是C的代理。在java中,B需要实现和C一样的接口,这样B才能代理C完成任务,实际的任务的完成还是有C来完成。

    静态代理:在编译时,代理类的.class文件就已经存在。

    动态代理:在运行时,动态生成代理类。很显然动态代理的实现需要用到java的反射机制。

2.为什么要使用动态代理?

    相对于不使用代理的情况,使用代理可以在调用被代理类的方法时,添加其他操作,比如过滤消息、对消息预处理以及消息处理之后等操作。

    相对于静态代理来说,静态代理在编译时,被代理类就必须存在,且每个代理对象中都会包含一个被代理对象,这样会导致类急剧膨胀。

3. 如何使用动态代理

    动态代理的实现主要依赖于Proxy类和InvocationHandler接口。

    Proxy类中的Static Object newProxyInstance(ClassLoader loader, Class[] intefaces, InvocationHandler h)函数会做:1.根据interfaces动态生成代理类proxy.$Proxy0 2.生成一个proxy.$Proxy0的对象并返回给调用者 3.调用者调用proxy.$Proxy0中的方法时,最终会通过调用h中的invoke()函数来调用被代理类的方法。

    InvocationHandler接口通常会被代理类继承,接口实例会被传入到newProxyInstance()方法,动态代理类的对象最终会通过InvocationHandler中的invoke()函数来调用被代理的对象,使用的是java反射机制。

Subject.java:

package com.zhb.dynamicproxy;public interface Subject {void request();}

AnotherSubject.java:

package com.zhb.dynamicproxy;public interface AnotherSubject {public String Hello(String a);}

DynamicSubject.java:

package com.zhb.dynamicproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;//需要实现InvocationHandler接口public class DynamicSubject implements InvocationHandler {private Object sub;public DynamicSubject(Object o){this.sub = o;//将真实角色的对象保存到sub中}public Object invoke(Object arg0, Method arg1, Object[] arg2)throws Throwable {Object o = null;System.out.println("before invoke:"+arg1.toString());o = arg1.invoke(sub, arg2);//通过反射调用真实角色sub的方法System.out.println("after invoke:"+arg1.toString());return o;}}

Client.java:

package com.zhb.dynamicproxy;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) throws Exception {RealSubject realSubject = new RealSubject();// 创建真实角色的对象InvocationHandler invocationHandler = new DynamicSubject(realSubject);// 初始化代理角色Class cls = realSubject.getClass();Class<?> c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces());// 根据真实角色 构建、返回一个proxy类Constructor<?> ctor = c.getConstructor(new Class[] { InvocationHandler.class });Subject subject2 = (Subject) ctor.newInstance(new Object[] { invocationHandler });// 创建一个之前构建的proxy类的接口对象subject2.request();AnotherSubject subject3 = (AnotherSubject) ctor.newInstance(new Object[] { invocationHandler });System.out.println(subject3.Hello("world"));// Proxy.newProxyInstance等价于上述三个函数,运行时动态生成一个proxy.$Proxy0类,该类实现了真实角色的接口,并返回proxy.$Proxy0的一个对象//把需要调用的接口cls.getInterfaces(),以及代理角色invocationHandler告诉 Proxy.newProxyInstance,该函数就会根据你提供的接口动态生成一个proxy.$Proxy0类,//并返回该类的一个对象subject,对subject调用相应的方法时,会调用invocationHandler中的invoke()函数,通过反射来调用真实角色的方法。Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), invocationHandler);subject.request();System.out.println(subject.getClass());AnotherSubject subject4 = (AnotherSubject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), invocationHandler);System.out.println(subject4.getClass() + " " + subject4.Hello("zhb"));}}

运行结果:

before invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
from realsubject
after invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
before invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
after invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
hello world
before invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
from realsubject
after invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
class com.sun.proxy.$Proxy0
before invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
after invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
class com.sun.proxy.$Proxy0 hello zhb

0 0
原创粉丝点击