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

  • 相关阅读:
    前端vue使用js-xlsx导出excel的三种方法
    vue使用echarts绘制河南地图并实现个人轨迹
    VUE中使用Echarts绘制柱状图
    springboot项目配置拦截器
    springboot+mybatis的多数据源配置
    Java后端高频面试题汇总
    Java基础专题
    Java集合专题
    Java并发专题
    JVM专题javascript:;
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/15250112.html
Copyright © 2011-2022 走看看