代理模式、静态代理及动态代理

代理模式


代理,就是帮别人做事情

你只需要去做你的事情就可以了,其他的事情交给代理来做

为什么要学习代理模式? 因为这就是SpringAOP的底层! 【面试高频 :SpringAOP,SpringMVC】

代理模式的分类:

  • 静态代理
  • 动态代理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ZQNCl5L-1611832820467)(Spring.assets/image-20201230141341876.png)]

真实对象 跟 代理对象 要去实现 租房接口

静态代理

角色分析:

  • 抽象角色:一般会用接口或者抽象类来解决

    //租房
    public interface Rent {
          
          
        public void rent();
    }
    
  • 真实角色:被代理的角色

    //房东
    public class Host implements Rent{
          
          
        public void rent() {
          
          
            System.out.println("房东要出租房子");
        }
    }
    
  • 代理角色:代理真实角色,代理后一般会做一些附属操作

    //代理角色
    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("收中介费");
        }
    }
    
  • 客户:访问代理对象的人

    //用户
    public class Client {
          
          
        public static void main(String[] args) {
          
          
            //房东要出租房子
            Host host = new Host();
            //代理房东出租房子,但是代理角色一般会有一些附属操作
            Proxy proxy = new Proxy(host);
    
            //通过代理租房子,不需要面对房东
            proxy.rent();
        }
    }
    /*  一开始是直接去找房东租房子
            现在很懒,想在网上找房子,就很难去找房东租房子了
                然后就去找到 中介 租房子。 中介帮房东出租房子
    */
    

静态代理模式的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
  • 公共业务也就交给代理角色!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生对应的代理角色,如果有多个真实角色 代码量会翻倍~开发效率会变低

静态代理加深理解

代理模式:就是不改变原有的业务情况下,给他增加一些功能、扩展一些功能

  1. 抽象角色
//抽象角色
public interface UserService {
    
    
    public void add();
    public void update();
    public void delete();
    public void select();
}
  1. 真实业务

    //真实业务 
    public class UserServiceImpl implements UserService{
          
          
        public void add() {
          
          
            System.out.println("新增一个方法");
        }
    
        public void update() {
          
          
            System.out.println("修改一个方法");
        }
    
        public void delete() {
          
          
            System.out.println("删除一个方法");
        }
    
        public void select() {
          
          
            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 update() {
          
          
            log("update");
            userService.update();
        }
    
        public void delete() {
          
          
            log("delete");
            userService.delete();
        }
    
        public void select() {
          
          
            log("select");
            userService.select();
        }
    
        public void log(String aa){
          
          
            System.out.println("输出了"+aa+"日志");
        }
    }
    
    1. 测试

      public class Client {
              
              
          public static void main(String[] args) {
              
              
              UserServiceImpl userService = new UserServiceImpl();
              
              UserServiceProxy userServiceProxy = new UserServiceProxy();
              userServiceProxy.setUserService(userService);
              userServiceProxy.add();
      
          }
      }
      

    AOP的底层就是代理模式,再不改变源码的情况写增加一些功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ppIWt3lX-1611832820471)(Spring.assets/image-20201231125930414.png)]

动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口: JDK动态代理 【下面使用这个】
    • 基于类: cglib
    • java字节码实现: javasist

需要了解两个类:Proxy 代理,InvocationHandler:调用处理程序

  • Proxy :提供了创建动态代理类和实例的静态方法

  • InvocationHandler: 调用处理程序实现的接口

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
  • 公共业务也就交给代理角色!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个代理类可以代理多个类,只要实现了同一个接口即可
//用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    
    

    //被代理的接口
    private Object target;          //代理谁
    public void setTarget(Object target) {
    
    
        this.target = target;
    }


    //生成代理类
    public Object getProxy(){
    
    
        /*    Proxy.newProxyInstance:生成一个代理对象
        this.getClass().getClassLoader():加载得到 类在哪个位置
        target.getClass().getInterfaces():表示要代理的接口是哪一个接口
        this:代表它自己的 InvocationHandler
 */
        return 	 Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    //调用代理程序的执行方法。 处理代理实例,并返回结果,就是你要代理的人,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        //如何判断是调用什么方法,通过反射获取到它的名字
        log(method.getName());
        //动态代理的本质,就是使用反射机制实现
        Object result = method.invoke(target, args);
        return result;
    }

    //增加一个日志功能
    public void log(String msg){
    
    
        System.out.println("增加了"+msg+"日志");
    }
}

测试:

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();

        //代理角色,不存在,需要通过 ProxyInvocationHandler去生成一个代理类。 因为它实现了InvocationHandler
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService); //设置要代理的对象

        //设置动态生成代理类
        UserService proxy = (UserService) pih.getProxy();

        proxy.delete();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45316925/article/details/113356259