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

posted @   Mars.wang  阅读(51)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示