23种设计模式之代理模式(动态代理)

一:什么是动态代理:

  利用反射机制在运行时创建代理类。接口、被代理类不变。

二:动态代理和静态代理的不同:

  1、静态代理的代理类是程序员事先写好的

  2、动态代理的代理类是在程序运行时动态生成的

三:动态代理分为两大类:

  1、基于接口的动态代理

  2、基于类的动态代理

四:动态代理的三种实现方式:

  1、基于接口--->JDK动态代理 (JAVA原生的)(我们在这里使用)

  2、基于类--->cglib (自己查阅资料做了解)

  3、java字节码实现---> javassist (查资料了解)

五:在使用动态代理之前,首先了解两大类

  1、Proxy  (代理)

  2、InvocationHandler  (调用处理程序)

六:动态代理代码展示  (房东出租房子案例)

  1、创建一个抽象角色

1 //租房的接口      (抽象角色)
2 
3 public interface Rent {
4 
5     //出租的方法
6     void rent();
7 
8 }

  2、创建真实角色,实现抽象角色接口

1 //房东 要出租房子   (真实的角色)
2 
3 public class Host implements Rent {
4     @Override
5     public void rent() {
6         System.out.println("房东要出租房子");
7     }
8 }

  3、首先,我们构建一个类来实现InvocationHandler接口           

 1 //动态生成代理
 2 
 3 public class ProxyInvocationHandler implements InvocationHandler {
 4 
 5     //被代理的接口
 6     private Rent rent;
 7 
 8     public void setRent(Rent rent) {
 9         this.rent = rent;
10     }
11 
12     //    Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
13 //            new Class<?>[] { Foo.class },
14 //            handler);
15 
16     //生成得到代理类   (通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例。针对不同的代理类,传入相应的代理程序控制器InvocationHandler)
17     public Object getProxy(){
18         return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
19 
20     }
21 
22     //处理代理实例,并返回结果
23     @Override
24     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
25 
26         //动态代理的本质,就是使用反射机制实现!
27         seeHouse();
28         Object result = method.invoke(rent, args);
29         fare();
30         return result;
31     }
32 
33     public void seeHouse(){
34         System.out.println("中介带看房子!");
35     }
36     public void fare(){
37         System.out.println("收中介费!");
38     }
39 }

  4、执行动态代理

 1 //执行动态代理,实现租房方法
 2 
 3 public class Client {
 4     public static void main(String[] args) {
 5         //真实角色
 6         Host host = new Host();
 7 
 8         //代理角色,现在没有
 9         ProxyInvocationHandler pih = new ProxyInvocationHandler();
10         //通过调用程序来处理我们要调用的接口对象!
11         pih.setRent(host);
12 
13         Rent proxy = (Rent) pih.getProxy();   //这里的proxy是动态生成的,我们并没有写!
14         //调用租房方法
15         proxy.rent();
16 
17     }
18 }

  5、输出结果

七:动态代理的具体步骤

    1、通过实现 InvocationHandler 接口创建自己的调用处理器;

    2、通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;

    3、通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

    4、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

八:动态代理的好处

    1、可以使真实角色的操作更加纯粹!不用去关注一些公共的业务

    2、公共业务就交给代理角色!实现了业务的分工!  

    3、公共业务发生扩展的时候,方便集中管理

    4、一个动态代理类代理的是一个接口,一般就是对应的一类业务

    5、一个动态代理类可以代理多个类,只要是实现了同一个接口即可

九:根据上述的动态代理实现机制,我们可以衍生出一个万能的动态代理类

 1 //万能的动态代理类
 2 
 3 public class ProxyInvocationHandler implements InvocationHandler {
 4 
 5     //被代理的接口
 6     private Object target;
 7 
 8     public void setTarget(Object target) {
 9         this.target = target;
10     }
11 
12     //    Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
13 //            new Class<?>[] { Foo.class },
14 //            handler);
15 
16     //生成得到代理类
17     public Object getProxy(){
18         return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
19 
20     }
21 
22     //处理代理实例,并返回结果
23     @Override
24     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
25 
26         //动态代理的本质,就是使用反射机制实现!
27         log(method.getName());
28         Object result = method.invoke(target, args);
29         return result;
30     }
31 
32     //根据不同业务需要,创建不同的扩展方法 (此处为打印日志)
33     public void log(String msg){
34         System.out.println("执行了"+msg+"方法!");
35     }
36 }

执行动态代理:

 1 //执行动态代理
 2 
 3 public class Client {
 4     public static void main(String[] args) {
 5         //真实角色
 6         UserServiceImpl userService = new UserServiceImpl();
 7 
 8         //代理角色,不存在
 9         ProxyInvocationHandler pih = new ProxyInvocationHandler();
10 
11         //设置要代理的对象
12         pih.setTarget(userService);
13 
14         //动态生成代理类
15         UserService proxy = (UserService) pih.getProxy();
16 
17         proxy.update();
18 
19     }
20 }

      注:抽象角色、真实角色 的实际代码此处省略(与静态代理实现步骤一样)

        【我们可根据不同的业务需求,套用万能动态代理模板即可】

 

 

 

 

 

posted @ 2020-07-21 22:52  你的龙儿  阅读(616)  评论(0编辑  收藏  举报