java动态代理

转载 2013年12月01日 23:44:53

没事的时候翻看lang.reflect包下的代码,发现有两部分内容:涉及反射和动态代理。
很多地方都可以看到动态代理的影子,只是一直没仔细看下。

在学习之前,先提出几个问题,带着问题来看代码:

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. }  

它的真实实现类:
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. }  

在这里生成与代理类相关联的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. }  

最后是测试类:
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. }  

这里是输出结果:
Java代码  收藏代码
  1. before....  
  2. print : All the test  
  3. after....  
  4. before....  
  5. Say hello to Denny  
  6. after....  

--------------------分隔线-----------------------------

最后试着来回答之前提出的问题:
1.什么是动态代理?
一种用于转发请求,进行特殊处理的机制,“动态”应该指的是“运行期”。
2.为什么使用动态代理?
可以对请求进行任何处理(如事务,日志等,这都是网上说的,我当然可以做任何处理)
3.使用它有哪些好处?
如上
4.哪些地方需要动态代理?
不允许直接访问某些类;对访问要做特殊处理等,我只能想到这些。


--------------------分隔线-----------------------------

其它一些想法:

1.如果想声明产生B类的代理类,那个B类必须要实现接口,如果没有接口,
代理类就不能伪装成B类的“兄弟”,也就没有存在的意思,
其实也可以伪装成B类的“孩子”,对外他们有共同的接口,可以这样做吧?

2.当请求代理类的方法时,这个请求会被转到执行与代理类关联InvocationHandler
的invoke方法。那InvocationHandler到底是什么?对它的理解可以是这样:
它用来处理方法的调用,实现类也有同样的意义;与代理类对象相关联则表示,
它就是负责处理代理类应该有的动作,把所有的方法请求分发到invoke这个方法上。




@ 符号 在java中是什么语法 代表什么

java中@是什么     J2SE 提供的最后一个批注是 @SuppressWarnings。该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。     一点背景:...
  • skyboy11yk
  • skyboy11yk
  • 2013年10月12日 16:49
  • 38777

关于java中<T>问题

关于java中问题 Jdk5.0新特性Generic Types (泛型) 原文 来源: 中国IT实验室 作者: 未知 责编: 宝良 1. 介绍 2.定义简单Java泛型 其实Java...
  • zhengqiqiqinqin
  • zhengqiqiqinqin
  • 2013年05月31日 19:22
  • 35831

Java中布尔类型操作&=,|=与^=的使用

今天在对同事的代码进行code review的时候,见到一个比较好玩的写法。“flag &= false;”,乍一看,还感觉他写错了,但是程序可以正常运行,赶紧去百度,看一下这个写法到底是怎么一回事,...
  • ziwen00
  • ziwen00
  • 2014年10月31日 16:35
  • 17998

java中==与equel的区别

值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。     ==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量...
  • hellokatewj
  • hellokatewj
  • 2014年03月26日 17:43
  • 2840

java this 3种常见用法 详解

this 关键字 1.区分成员变量和局部变量 2.代表当前对象 3.构造器之间调用
  • u012176204
  • u012176204
  • 2017年01月17日 09:41
  • 3102

【数据结构】之二叉树的java实现

二叉树的定义: 二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。...
  • wuwenxiang91322
  • wuwenxiang91322
  • 2013年10月02日 09:28
  • 80339

Java可以做什么及可以给我们带来什么?

一般来说,Java是一个功能强大的软件平台。一套完整的Java平台将会给你带来如下特性: 开发工具箱:...
  • stewen_001
  • stewen_001
  • 2014年03月12日 16:06
  • 2905

Java 进度条控件的使用

利用JProcessBar类可以实现一个进度条,它本身不过是一个矩形控件,通过填充它的部分或全部来指示一个任务的执行情况,可以放置到一个新的线程中运行。 示例如下:...
  • kehyuanyu
  • kehyuanyu
  • 2014年05月19日 17:44
  • 8691

最小堆和最大堆的JAVA实现

/** * 文件名:BinaryHeap.java * 时间:2014年11月3日下午7:15:34 * 作者:修维康 */ package chapter6; import java.ut...
  • xiuweikang
  • xiuweikang
  • 2014年11月04日 16:37
  • 4438

java事务处理全解析

最近学习java事务,看到一位前辈的系列博客不错,转载过来作为记录 转载地址:http://www.davenkin.me/post/2013-02-16/40048284001    (一)Ja...
  • huilangeliuxin
  • huilangeliuxin
  • 2015年02月03日 10:26
  • 55435
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java动态代理
举报原因:
原因补充:

(最多只允许输入30个字)