zoukankan      html  css  js  c++  java
  • Java设计模式之代理

    代理模式从业务上讲其实还是比较好理解的,比如过年我想买一张火车票,总也买不到,怎么办?

    比如可以让男朋友去火车站排队去买!这叫静态代理

    一、静态代理

    首先我们定义一个接口,买火车票

    public interface BuyTicket {
        public void buy();
    }

    然有个美女,想要回家,需要买一张火车票

    public class BuyTicketGirl implements BuyTicket {
        @Override
        public void buy() {
            System.out.println("I need a ticket");
        }
    }

    很遗憾,过年的时候火车票不好买,美女只好求男朋友去帮忙买

    public class BuyTicketBoy implements BuyTicket {
    
        private BuyTicket buyTicket;
    
        public BuyTicketBoy(BuyTicket buyTicket) {
            this.buyTicket = buyTicket;
        }
    
        @Override
        public void buy() {
            System.out.println("I am boy friend");
            buyTicket.buy();
        }
    }
    public class Main {
        public static void main(String[] args) {
            BuyTicket buyTicket = new BuyTicketGirl();
            BuyTicket proxy = new BuyTicketBoy(buyTicket);
            proxy.buy();
    }
    }

    买到了,输出:

    I am boy friend
    I need a ticket

    很好,但这有一个问题,如果让男朋友帮忙买票,前提是每个人都有男朋友,显然这并不现实。

    这也是静态代理的缺点:代理只能为一个类服务,如果需要为很多类服务,需要写很多代理类,这并不是我们想看到的。

    那怎么办?

    如果你去过火车站,会发现火车站就会有一些到处晃悠的大哥悄没声问:买票不?

    对于买票这个行为来说,他的身份就是代理,他能帮我完成买票这个行为,具体他是谁,怎么做到,我不关心。

    而且在买票这个事上,他能帮很多人实现梦想。这就是动态代理。

    二、动态代理

    首先我们先实现一个买票大哥,他持有一个object属性,意味他可以为所有人帮忙买票,如果你需要,说不定还可以帮忙买房买车。

    public class ProxyHandler implements InvocationHandler {
    
        private Object object;
    
        public ProxyHandler(Object object) {
            this.object = object;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("I am Dynamic Proxy");
            method.invoke(object,args);
            return null;
        }
    }

    开始买票

    public class Main {
        public static void main(String[] args) {
            BuyTicket buyTicket = new BuyTicketGirl();
    
            ProxyHandler proxyHandler = new ProxyHandler(buyTicket);
            BuyTicket proxyInstance = (BuyTicket) Proxy.newProxyInstance(
                    buyTicket.getClass().getClassLoader(),
                    buyTicket.getClass().getInterfaces(),
                    proxyHandler);
    
            proxyInstance.buy();
    }
    }

    输出:

    I am Dynamic Proxy
    I need a ticket

    也买到票了,这就是动态代理

    三、动态代理底层原理

    实际上JDK动态代理是采用字节重组,重新生成对象来代替原始对象以达到动态代理的目的。JDK Proxy生成对象的步骤如下。

    1.拿到被代理对象的引用BuyTicket 并且获取到它所有的接口反射获取。(这也是为什么JDK动态代理需要代理类和被代理类都要事先同一接口的原因)

    2.JDK Proxy类重新生成一个新的类,这个新的类需要实现被代理类(BuyTicket)的所有实现的所有接口(buy)

    3.动态生成java代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现)

    4.编译新生成的java代码.class

    5.再重新加载到JVM中运行


    四、Spring AOP中的代理机制

    springboot没有默认使用的代理 : (SpringBoot中默认开启了proxyTargetClass,默认都是使用CGLIB代理)
    • 如果代理的是实现接口的类,则使用JDK动态代理. 只要代理的类实现了至少一个接口,那么目标类型实现的接口都将会使用JDK动态代理
    • 如果代理的是子类,没有实现任何接口,则使用CGLIB代理


    参考:

    https://www.jianshu.com/p/8aee43cbc373

    https://www.jianshu.com/p/ab6b0c9d549c

    https://www.jianshu.com/p/9bcac608c714

  • 相关阅读:
    Windows 科研软件推荐
    有关Python 包 (package) 的基本知识
    《Using Python to Access Web Data》Week4 Programs that Surf the Web 课堂笔记
    Coursera助学金申请模板
    《Using Databases with Python》 Week2 Basic Structured Query Language 课堂笔记
    Jupyter 解决单个变量输出问题
    解决 pandas 中打印 DataFrame 行列显示不全的问题
    《Using Python to Access Web Data》 Week3 Networks and Sockets 课堂笔记
    缓存击穿及解决方案
    jvm垃圾收集器
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/15250112.html
Copyright © 2011-2022 走看看