动态代理是相对静态代理而说的,比较废话一句。其核心就是Proxy.newProxyInstance生产代理类,同时指定这个代理实例的回调接口java.lang.reflect.InvocationHandler。先上代码,再做分析:

 1 /**
 2  * User服务接口类
 3  */
 4 interface UserService{
 5     /**
 6      * 添加一个用户
 7      * @return
 8      */
 9     public boolean add(String name);
10 }
 1 /**
 2  * User服务接口实现类
 3  */
 4 class UserServiceImpl implements UserService{
 5 
 6     @Override
 7     public boolean add(String name) {
 8         System.out.println(String.format("添加一个名为:%s的用户", name));
 9         return true;
10     }
11 }
 1 /**
 2  * 代理工具类,用其他类提供代理
 3  */
 4 class DynamicProxyUtil implements InvocationHandler{
 5     /**
 6      * 被代理的对象
 7      */
 8     private Object proxyObject;
 9     /**
10      * 将被代理对象传入,以便生产代理类
11      * @param proxyObject
12      * @return
13      */
14     public Object generateProxyClass(Object proxyObject){
15         this.proxyObject=proxyObject;//将被代理对象引入该类
16         //根据被代理对象的类信息生产代理类    
17         Class<?> clazz = proxyObject.getClass();
18         /*Proxy.newProxyInstanc方法实现原理:jvm会根据传入的接口及其实现类动态生成如:$Proxy.class字节码类,默认只在内存中,可使用
19         System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")将类文件保存在本地磁盘
20         $Proxy0 实现要代理的对象接口及其托管对被代理对象所有方法调用
21         public final class $Proxy0 extends java.lang.reflect.Proxy implements UserService
22         */
23         return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
24     }
25     @Override
26     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
27         System.out.println(String.format("方法%s调用前,传入参数%s", method.getName(),Arrays.toString(args)));
28         Object result = method.invoke(this.proxyObject, args);
29         System.out.println(String.format("方法%s调用前,返回值%s", method.getName(),result));
30         return result;
31     }
32     
33 }
 1 /**
 2  * 测试类
 3  */
 4 public class ClientTest {
 5     public static void main(String[] args) {
 6         
 7         UserService userService = new UserServiceImpl();
 8         //用代理工具类生成一个UserService服务代理
 9         System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
10         DynamicProxyUtil dynamicProxy = new DynamicProxyUtil();
11         UserService userServiceProxy = (UserService)dynamicProxy.generateProxyClass(userService);
12         //通过生成的代理类来调用方法,而不是直接调用userService.add。这样我们就可以动态调用服务方法,以便在代理工具类中动态加入其他业务逻辑代码,如系统日志记录等等
13         //spring aop默认就是使用JdkDynamic实现代理bean的,spring aop还有一种就是cglib动态字节码生成类工具包
14         boolean result = userServiceProxy.add("muzi");
15         System.out.println(result?"添加成功":"添加失败");
16     }
17 }

 再复习代理模式定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

其实jdk动态代理实现也能简单,就是动态生成一个代理类如:$Proxy0(可通过反编译软件查看保存在本地磁盘上的.class),如下所示:

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 import java.lang.reflect.Proxy;
 4 import java.lang.reflect.UndeclaredThrowableException;
 5 /**
 6  *该类就是动态生成的类,省略掉无用代码 ,此类自动实现UserService接口,就是
 7  *Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
 8  *方法的第二个参数,所以我们可以将生成的代理强制类型转换为UserService接口类型对象,注意而不能转换为UserServiceImpl实现类对象
 9  */
10 public final class $Proxy0 extends Proxy implements UserService {
11 
12     public $Proxy0(InvocationHandler invocationhandler) {
13         super(invocationhandler);
14     }
15 
16     public final boolean add(String s) {
17         try {
18             //调用InvocationHandler回调接口中的回调方法,此为关键代码,就是DynamicProxyUtil.invoke方法
19             return ((Boolean) super.h.invoke(this, m3, new Object[] { s })).booleanValue();
20         } catch (Error _ex) {
21         } catch (Throwable throwable) {
22             throw new UndeclaredThrowableException(throwable);
23         }
24         return false;
25     }
26 
27     private static Method m3;
28 
29     static {
30         try {
31             //根据java反射机制构造UserService中add方法Method类型实例
32             m3 = Class.forName("UserService").getMethod("add", new Class[] { Class.forName("java.lang.String") });
33         } catch (NoSuchMethodException nosuchmethodexception) {
34             throw new NoSuchMethodError(nosuchmethodexception.getMessage());
35         } catch (ClassNotFoundException classnotfoundexception) {
36             throw new NoClassDefFoundError(classnotfoundexception.getMessage());
37         }
38     }
39 }

 

ps:描述不是很具有条理性,对付着看吧,多跟两趟代码就清楚了

所用到工具下载链接:

jd-gui:http://pan.baidu.com/share/link?shareid=378349&uk=973960637

 

 

posted on 2013-04-13 10:20  lixiangqian  阅读(304)  评论(2编辑  收藏  举报