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

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

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

  • 相关阅读:
    USACO 5.1 Starry Night
    USACO 4.4 Frame Up
    USACO 4.4 Shuttle Puzzle
    USACO 4.3 Letter Game (字典树)
    USACO 4.3 Street Race
    BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)
    BZOJ 1861: [Zjoi2006]Book 书架 (splay)
    codeforces 354 D. Transferring Pyramid
    codeforces 286 E. Ladies' Shop (FFT)
    USACO 4.3 Buy Low, Buy Lower
  • 原文地址:https://www.cnblogs.com/liangbaolong/p/13357932.html
Copyright © 2020-2023  润新知