• 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();
            }
        }
        

    四、动态代理的好处

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

    • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
    • 公共的业务由代理来完成 . 实现了业务的分工 ,
    • 公共业务发生扩展时变得更加集中和方便 .
    • 一个动态代理 , 一般代理某一类业务
    • 一个动态代理可以代理多个类,代理的是接口!
  • 相关阅读:
    Fancybox丰富的弹出层效果
    oracle wm_concat(column)函数的使用
    asp.net下ajax.ajaxMethod使用方法
    sql2008 附加数据库出错解决方法
    关于mysql-5.7.13-winx64服务无法启动的解决方法
    解决懒加载异常
    学生各科成绩,平均分,总分的展示
    docker desktop v20 设置文件路径,windows docker 设置设置路径
    自动化运维工具:jumpserver/jms_all
    linux kill 进程正则表达式
  • 原文地址:https://www.cnblogs.com/dreamzone/p/12402827.html
Copyright © 2020-2023  润新知