zoukankan      html  css  js  c++  java
  • Spring:(六) 代理模式

    一、前言

    • 代理模式
      • 静态代理
      • 动态代理

    二、静态代理

    1. 角色分析

      • 抽象角色 : 一般使用接口或者抽象类来实现
      • 真实角色 : 被代理的角色
      • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
      • 客户 : 使用代理角色来进行一些操作 .
    2. 实现(中介租房)

      1. Rent :抽象角色

        //抽象角色:租房
        public interface Rent {
            public void rent();
        }
        
      2. Host . java 即真实角色

        //真实角色: 房东,房东要出租房子
        public class Host implements Rent{
            public void rent() {
                System.out.println("房屋出租");
            }
        }
        
      3. Proxy . java 即代理角色

        //代理角色:中介
        public class Proxy implements Rent {
        
            private Host host;
            public Proxy() { }
            public Proxy(Host host) {
                this.host = host;
            }
        
            //租房
            public void rent(){
                seeHouse();
                host.rent();
                fare();
            }
            //看房
            public void seeHouse(){
                System.out.println("带房客看房");
            }
            //收中介费
            public void fare(){
                System.out.println("收中介费");
            }
        }
        
      4. Client . java 即客户

        //客户类,一般客户都会去找代理!
        public class Client {
            public static void main(String[] args) {
                //房东要租房
                Host host = new Host();
                //中介帮助房东
                Proxy proxy = new Proxy(host);
        
                //你去找中介!
                proxy.rent();
            }
        }
        

        静态代理的好处

        • 使得真实角色更加纯粹 . 不再去关注一些公共的事情
        • 公共的业务由代理来完成 . 实现了业务的分工 ,
        • 公共业务发生扩展时变得更加集中和方便 .

        缺点

        • 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .
    3. 实现2(t用户增删改查)

      1.什么事

      //抽象角色:增删改查业务
      public interface UserService {
          void add();
          void delete();
          void update();
          void query();
      }
      
      1. 真实对象来完成这些增删改查操作

        //真实对象,完成增删改查操作的人
        public class UserServiceImpl implements UserService {
        
            public void add() {
                System.out.println("增加了一个用户");
            }
        
            public void delete() {
                System.out.println("删除了一个用户");
            }
        
            public void update() {
                System.out.println("更新了一个用户");
            }
        
            public void query() {
                System.out.println("查询了一个用户");
            }
        }
        
      2. 需要增加一个日志功能,怎么实现,找代理最方便

        //代理角色,在这里面增加日志的实现
        public class UserServiceProxy implements UserService {
            private UserServiceImpl userService;
        
            public void setUserService(UserServiceImpl userService) {
                this.userService = userService;
            }
        
            public void add() {
                log("add");
                userService.add();
            }
        
            public void delete() {
                log("delete");
                userService.delete();
            }
        
            public void update() {
                log("update");
                userService.update();
            }
        
            public void query() {
                log("query");
                userService.query();
            }
        
            public void log(String msg){
                System.out.println("执行了"+msg+"方法");
            }
        
        }
        
        1. 测试

          public class Client {
              public static void main(String[] args) {
                  //真实业务
                  UserServiceImpl userService = new UserServiceImpl();
                  //代理类
                  UserServiceProxy proxy = new UserServiceProxy();
                  //使用代理类实现日志功能!
                  proxy.setUserService(userService);
          
                  proxy.add();
              }
          }
          

    三、动态代理

    1. 简介
    • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
    • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
    • 基于接口的动态代理----JDK动态代理
    • 基于类的动态代理--cglib
    • 现在用的比较多的是 javasist 来生成动态代理

    1. JDK的动态代理需要了解两个类
    • 核心 : InvocationHandler 和 Proxy

    • InvocationHandler

      • InvocationHandler 是由代理实例的,调用处理程序实现的接口

      • 每个代理实例都有一个关联的调用处理程序,在代理实例上调用方法的时候,方法调用将被编码,并分派到其调用处理程序的invoke方法

      • Object invoke(Object proxy, 方法 method, Object[] args);
        //参数 
        //proxy - 调用该方法的代理实例 
        //method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。 
        //args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。 
        
    • Proxy

      • //生成代理类

      • //生成代理类
        public Object getProxy(){
            return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                                          rent.getClass().getInterfaces(),this);
        }
        
    1. 实现

      • 实体类

        //抽象角色:租房
        public interface Rent {
            public void rent();
        }
        
      • Host真实角色

        //真实角色: 房东,房东要出租房子
        public class Host implements Rent{
            public void rent() {
                System.out.println("房屋出租");
            }
        }
        
      • ProxyInvocationHandler. java 即代理角色

        public class ProxyInvocationHandler implements InvocationHandler {
            private Rent rent;
        
            public void setRent(Rent rent) {
                this.rent = rent;
            }
        
            //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
            public Object getProxy(){
                return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                        rent.getClass().getInterfaces(),this);
            }
        
            // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
            // 处理代理实例上的方法调用并返回结果
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                seeHouse();
                //核心:本质利用反射实现!
                Object result = method.invoke(rent, args);
                fare();
                return result;
            }
        
            //看房
            public void seeHouse(){
                System.out.println("带房客看房");
            }
            //收中介费
            public void fare(){
                System.out.println("收中介费");
            }
        
        }
        
      • Client . java

        public class Test {
            public static void main(String[] args) {
                //真实对象
                Host host = new Host();
                //代理对象的调用处理程序
                ProxyInvocationHandler pih = new ProxyInvocationHandler();
                pih.setRent(host); //设置要代理的对象
                UserService proxy = (UserService)pih.getProxy(); //动态生成代理类!
                proxy.delete();
            }
        }
        

    四、动态代理的好处

    静态代理有的它都有,静态代理没有的,它也有!

    • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
    • 公共的业务由代理来完成 . 实现了业务的分工 ,
    • 公共业务发生扩展时变得更加集中和方便 .
    • 一个动态代理 , 一般代理某一类业务
    • 一个动态代理可以代理多个类,代理的是接口!
  • 相关阅读:
    PAT (Advanced Level) 1080. Graduate Admission (30)
    PAT (Advanced Level) 1079. Total Sales of Supply Chain (25)
    PAT (Advanced Level) 1078. Hashing (25)
    PAT (Advanced Level) 1077. Kuchiguse (20)
    PAT (Advanced Level) 1076. Forwards on Weibo (30)
    PAT (Advanced Level) 1075. PAT Judge (25)
    PAT (Advanced Level) 1074. Reversing Linked List (25)
    PAT (Advanced Level) 1073. Scientific Notation (20)
    PAT (Advanced Level) 1072. Gas Station (30)
    PAT (Advanced Level) 1071. Speech Patterns (25)
  • 原文地址:https://www.cnblogs.com/dreamzone/p/12402827.html
Copyright © 2011-2022 走看看