当前位置: 首页 > news >正文

java 动态代理

1.什么是动态代理? 2.为什么使用动态代理? 3.使用它有哪些好处?
4.哪些地方需要动态代理? 
和动态代理有关的有两个类 1.interface InvocationHandler Object invoke(Object proxy, Method method, Object[] args) 只这一个方法,后面再说
2.class Proxy
真正表示动态代理的类,提供两个静态方法:
Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”, 用来冒充真实的对象。
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法, invoke方法就是我们用来做N多事情的地方 -_-。 

看完上面的代码,大致明白动态代理的含义: A接口有c方法,类B实现A接口,原本应该是执行B类中的c方法,可现在不这样做;
我声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口, 对外界来说B'应该也有c方法,可当真正调用它的时候,
它会去执行与它关联InvocationHandler的invoke()方法,
在这个方法里面你可以做很多事情。这样,这个请求就被“代理”到其它地方去了。
下面是根据我的理解画的一个说明图  

引用网上的一个例子来说明问题(有部分改动,转载自:http://callan.iteye.com/blog/161806) 真实的接口:

Java代码  
  1. public interface Hello {   
  2.   
  3.     void sayHello(String to);   
  4.      
  5.     void print(String p);    
  6.     
  7. }  
public interface Hello {

    void sayHello(String to);
  
    void print(String p); 
 
}

它的真实实现类:

Java代码  
  1. public class HelloImpl implements Hello {   
  2.        
  3.     public void sayHello(String to) {   
  4.         System.out.println("Say hello to " + to);   
  5.     }   
  6.        
  7.     public void print(String s) {   
  8.         System.out.println("print : " + s);   
  9.     }   
  10.        
  11. }  
public class HelloImpl implements Hello {
    
    public void sayHello(String to) {
        System.out.println("Say hello to " + to);
    }
    
    public void print(String s) {
        System.out.println("print : " + s);
    }
    
}

在这里生成与代理类相关联的InvocationHandler对象

Java代码  
  1. public class LogHandler implements InvocationHandler {   
  2.        
  3.     private Object dele;   
  4.        
  5.     public LogHandler(Object obj) {   
  6.         this.dele = obj;   
  7.     }   
  8.        
  9.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
  10.         doBefore();   
  11.         //在这里完全可以把下面这句注释掉,而做一些其它的事情   
  12.         Object result = method.invoke(dele, args);   
  13.         after();   
  14.         return result;   
  15.     }   
  16.        
  17.     private void doBefore() {   
  18.         System.out.println("before....");   
  19.     }   
  20.        
  21.     private void after() {   
  22.         System.out.println("after....");   
  23.     }   
  24. }  
public class LogHandler implements InvocationHandler {
    
    private Object dele;
    
    public LogHandler(Object obj) {
        this.dele = obj;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        doBefore();
        //在这里完全可以把下面这句注释掉,而做一些其它的事情
        Object result = method.invoke(dele, args);
        after();
        return result;
    }
    
    private void doBefore() {
        System.out.println("before....");
    }
    
    private void after() {
        System.out.println("after....");
    }
}

最后是测试类:

Java代码  
  1. public class ProxyTest {   
  2.   
  3.     public static void main(String[] args) {   
  4.         HelloImpl impl = new HelloImpl();   
  5.         LogHandler handler = new LogHandler(impl);   
  6.         //这里把handler与impl新生成的代理类相关联   
  7.         Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);   
  8.            
  9.         //这里无论访问哪个方法,都是会把请求转发到handler.invoke   
  10.         hello.print("All the test");   
  11.         hello.sayHello("Denny");   
  12.     }   
  13.   
  14. }  
public class ProxyTest {

    public static void main(String[] args) {
        HelloImpl impl = new HelloImpl();
        LogHandler handler = new LogHandler(impl);
        //这里把handler与impl新生成的代理类相关联
        Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);
        
        //这里无论访问哪个方法,都是会把请求转发到handler.invoke
        hello.print("All the test");
        hello.sayHello("Denny");
    }

}

这里是输出结果:

Java代码  
  1. before....   
  2. print : All the test   
  3. after....   
  4. before....   
  5. Say hello to Denny   
  6. after....  
before....
print : All the test
after....
before....
Say hello to Denny
after....
 最后试着来回答之前提出的问题: 1.什么是动态代理?
一种用于转发请求,进行特殊处理的机制,“动态”应该指的是“运行期”。 2.为什么使用动态代理?
可以对请求进行任何处理(如事务,日志等,这都是网上说的,我当然可以做任何处理) 3.使用它有哪些好处? 如上
4.哪些地方需要动态代理? 不允许直接访问某些类;对访问要做特殊处理等,我只能想到这些。
其它一些想法:
1.如果想声明产生B类的代理类,那个B类必须要实现接口,如果没有接口,
代理类就不能伪装成B类的“兄弟”,也就没有存在的意思, 其实也可以伪装成B类的“孩子”,对外他们有共同的接口,可以这样做吧?
2.当请求代理类的方法时,这个请求会被转到执行与代理类关联InvocationHandler
的invoke方法。那InvocationHandler到底是什么?对它的理解可以是这样:
它用来处理方法的调用,实现类也有同样的意义;与代理类对象相关联则表示,
它就是负责处理代理类应该有的动作,把所有的方法请求分发到invoke这个方法上。

相关文章:

  • 字符缓冲流BufferedWriter和BufferedWriter
  • 修改BASH的配色
  • OpenStack快照分析:(三)从磁盘启动云主机离线(在线)快照分析
  • php substr说明
  • alterdialog
  • MobIM-API说明
  • mysql5.5.15配置主从数据库
  • 京东美团研发面经
  • windos使用nslookup查询mx记录
  • canvas - drawImage()方法绘制图片不显示的问题
  • JavaScript的性能优化:加载和执行
  • 建站利器 | 阿里巴巴上线静态开源站点搭建工具 Docsite
  • 【SDOI2009】Bill的挑战
  • java与C#的简单比较
  • 关于malloc的一个未解决的疑问
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • C++类的相互关联
  • ES10 特性的完整指南
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • JavaScript 基础知识 - 入门篇(一)
  • Java应用性能调优
  • PhantomJS 安装
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • Web设计流程优化:网页效果图设计新思路
  • Windows Containers 大冒险: 容器网络
  • 从零开始学习部署
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 多线程事务回滚
  • 解决iview多表头动态更改列元素发生的错误
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 学习HTTP相关知识笔记
  • 原生js练习题---第五课
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​油烟净化器电源安全,保障健康餐饮生活
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • %check_box% in rails :coditions={:has_many , :through}
  • (11)MATLAB PCA+SVM 人脸识别
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (27)4.8 习题课
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (三)Honghu Cloud云架构一定时调度平台
  • (十八)三元表达式和列表解析
  • (一)VirtualBox安装增强功能
  • .bashrc在哪里,alias妙用
  • .md即markdown文件的基本常用编写语法
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .net 提取注释生成API文档 帮助文档
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NET企业级应用架构设计系列之结尾篇
  • .NET中winform传递参数至Url并获得返回值或文件