动态代理
来源:互联网 发布:人工智能的现状论文 编辑:程序博客网 时间:2024/05/29 14:29
动态代理,简单说就是不用在设计实现的时候就指定某一个代理类来代理哪一个被代理的对象,可以把这种指定延迟到程序运行时有JVM来实现。它的结构图如下:
其中:
InvocationHandler:即为java.reflect.InvocationHandler接口;
AbstractSubject:抽象主题类;
RealSubject:真实主题类,即被代理的类;
DynamicProxy:动态代理类,需要实现InvocationHandler接口。
为了让DynamicProxy类能够在运行时才实现RealSubject类已经实现的一系列接口并执行接口中的方法操作,需让DynamicProxy类实现JDK自带的Java.lang.reflect.InvocationHandler接口,因为该接口中的invoke()方法能够让DynamicProxy实例在运行时调用被代理类的“对外服务”,即调用被代理类需要对外实现的所有接口中的方法,也就是完成对真实方法的调用。
代码实例如下:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//抽象主题类interface AbstractSubject{ public abstract void request();}//被代理的类class RealSubject implements AbstractSubject{ public void request(){ System.out.println("被代理类的请求"); }}//动态代理类class DynamicProxy implements InvocationHandler{ Object obj=null;//被代理类的实例 //将被代理类的实例传进动态代理类的构造函数中 public DynamicProxy(Object obj){ this.obj=obj; } //覆盖了InvocationHandler中的invoke()方法 public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{ //在该方法之前,可以进行特殊代码切入的扩展点,可增强其功能; Object result=method.invoke(this.obj, args); return result; //在该方法之后,可以进行特殊代码切入的扩展点,可增强其功能; }}public class Client{ public static void main(String[] args){ // 定义一个被代理类的实例 AbstractSubject realSubject=new RealSubject(); //获取被代理类的类加载器,使得JVM能够加载并找到被代理类的内部结构,以及已经实现的interface ClassLoader loader=realSubject.getClass().getClassLoader(); //获取被代理类已经实现的所有接口 Class<?> [] interfaces=realSubject.getClass().getInterfaces(); //用被代理类的实例创建动态代理类的实例,用于真正调用处理程序 InvocationHandler handler=new DynamicProxy(realSubject); //获取代理类的实例,newProxyInstance()方法中的参数:loader是被代理类的类加载器;interfaces是被代理类已经实现的所有接口;handle是动态代理类实例 AbstractSubject proxy=(AbstractSubject) Proxy.newProxyInstance(loader, interfaces, handler); proxy.request(); System.out.println(proxy.getClass().getName()); }}//运行结果为://被代理类的请求//$Proxy0
动态代理模式可以使我们在不改变原来已有的代码结构的情况下,即不用修改源码的情况下,对原来的“真实方法”进行扩展,增强其功能,在方法执行前后增加任何想要的功能,因为在InvocationHandler的invoke方法中,可以直接获取正在调用方法所对应的Method对象,具体的应用,如可以做事物控制,添加调用日志等。并且可以达到控制被代理对象的行为。
一般创建一个动态代理对象分为4个步骤:
(1)通过实现InvocationHandler接口创建自己的调用处理器,`InvocationHandler handler=new DynamicProxy(…);
(2)通过Proxy类指定ClassLoad对象和一组interface,创建动态代理类
Class clazz=Proxy.getProxyClass(classLoader,new Class[]{...});
(3)通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口的类型:
Constructor constructor=clazz.getConstructor(new Class[]{InvocationHandler.class});
(4)通过构造函数创建代理类实例,此时需要将调用处理器对象作为参数传入:
Interface Proxy=(Interface)constructor.newInstance(new Object[](handler));
但是一般会进行简化,将(2)-(4)三个步骤进行封装,用到了Proxy类中的newProxyInstance()方法,正如上述程序中所实现的。
- 代理-->静态代理&动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- ansible-playbook简介
- [UVA816] Abbott's Revenge BFS
- UE4 AIController的位置问题
- javascript callback函数的理解与使用
- js判断对象构造函数
- 动态代理
- Android UI 设计参考资源
- 条件运算符的使用(Java)
- Python-条件判断和循环
- ZOJ-3870 Team Formation(位运算)
- 国内首家多点触摸电容屏驱动课程上线啦!
- AOP初识
- bzoj1197: [HNOI2006]花仙子的魔法
- 大数据、云计算系统高级架构师课程学习路线图