代码改变世界

设计模式--动态代理

2018-09-08 21:33  小兵故事  阅读(187)  评论(0编辑  收藏  举报

本博客借鉴https://www.cnblogs.com/baizhanshi/p/6611164.html

静态代理

优点

代理是客户端不需要知道实现类是什么,怎么做,而客户端只需要知道代理即可(解耦合)

缺点

1)代理类和目标类实现了相同的接口,代理类通过目标类实现了相同的方法。这样就会出现大量的代码重复,比如目标列增加一个方法,代理类就也要增加相应的方法

2)代理类只是为一个目标类服务,如果需要为多个目标类服务就不适应了

 

改用办法采用动态代理

 1 package com.study.proxy;
 2 
 3 /**
 4  * 目标接口
 5  * @author xiaojuan
 6  *
 7  */
 8 public interface IDBQuery {
 9     //查询用户
10     public String getUser();
11     //查询账户
12     public String getAccout();
13     //查询金额
14     public String getTxn();
15 }
目标接口
 1 package com.study.proxy;
 2 
 3 /**
 4  * 目标实现类
 5  * @author xiaojuan
 6  *
 7  */
 8 public class DBQueryImpl implements IDBQuery{
 9 
10     @Override
11     public String getUser() {
12         return "zhangsan";
13     }
14 
15     @Override
16     public String getAccout() {
17         // TODO Auto-generated method stub
18         return "4646446464";
19     }
20 
21     @Override
22     public String getTxn() {
23         // TODO Auto-generated method stub
24         return "45.21";
25     }
26     
27     
28     
29 
30 }
目标实现类
 1 package com.study.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 
 7 public class DBQueryDynamicProxy implements InvocationHandler{
 8 
 9     //目标对象
10     private Object target;
11     
12     //关联的这个实现类的方法被调用时将被执行时,执行invoke方法
13     //InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数
14     //
15     @Override
16     public Object invoke(Object proxy, Method method, Object[] args)
17             throws Throwable {
18         System.out.println("开始查询数据库:》》》》");
19         //调用目标方法
20         Object ret = method.invoke(target, args);
21         return ret;
22     }
23     
24     //获取代理对象
25     public Object createProxy(Object target) {
26         //指定目标对象
27         this.target = target;
28         //该方法用于指定类加载器、一组接口及调用处理器生成动态代理类实例
29         //第一个参数产生代理对象的类加载器,需要将指定为目标对象同一个类加载器
30         //第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的接口
31         //第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
32         Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
33         return proxy;
34     }
35 
36 }
动态代理类
 1 package com.study.proxy;
 2 
 3 public class Test {
 4 
 5     public static void main(String[] args) {
 6         DBQueryDynamicProxy proxy = new DBQueryDynamicProxy();
 7         IDBQuery query = (IDBQuery) proxy.createProxy(new DBQueryImpl());
 8         System.out.println(query.getUser());
 9         System.out.println(query.getAccout());
10 
11     }
12 
13 }
测试类