ProxyFactory.getProxy() 类型转换问题 | JDK动态代理与CGLIB代理

今天在看《Spring5 高级编程》AOP那个章节的时候遇到一个问题

书中在实例化 ProxyFactory 时都是用的无参构造器,然后再调用父类 AdvisorSupport 中的setTarget() 方法来设置目标对象,但是 ProxyFactory 中存在一个可以直接传入目标对象的构造器:

点进去看这个构造器:

也是调用了父类 AdvisorSupport 中的 setTarget(Object target)方法,试下能不能直接用这个构造函数

省流版:不行,因为这个构造方法中还调用了 setInterfaces() 方法。指定了接口类型,会使用JDK动态代理,JDK动态代理的对象不能转换为具体的类型。


产生了如下报错:

debug看一下这两种写法有什么区别:

ProxyFactory factory = new ProxyFactory(guitarist)

使用了JDK动态代理,JDK动态代理生成的代理对象不是目标对象的类类型(即 Guitarist 类),而是一个实现了目标对象接口的代理类。

因此,改成这种写法则不会报错:

public static void main(String[] args) {
        Guitarist guitarist = new Guitarist();

        ProxyFactory factory = new ProxyFactory(guitarist);
        Singer proxy = (Singer) factory.getProxy();

        System.out.println("Proxy class: " + proxy.getClass());
        System.out.println("Is CGLIB proxy: " + (proxy.getClass().getName().contains("CGLIB")));
    }

如果尝试将这个代理对象强制转换为目标对象的具体类类型(Guitarist 类),会抛出 ClassCastException


ProxyFactory factory = new ProxyFactory();

factory.setTarget(guitarist);

使用这种写法时,采用了CGLIB 代理,CGLIB 代理通过创建目标类的子类实现代理,因此代理对象可以被强制转换为目标类。

** 会触发CGLIB 代理 的情况:

  • 代理对象被强制生成为类代理

    • 如果你没有通过接口类型来访问代理对象,而是直接访问目标类类型(例如 Guitarist),Spring 可能会选择使用 CGLIB,因为 JDK 动态代理不能代理具体的类。
  • 未指定接口

    • ProxyFactory 中,如果未显式告知代理对象应该实现哪些接口,Spring 会更倾向于使用 CGLIB,因为它可以代理具体类。
    • 如果目标类实现了接口,且调用 factory.setInterfaces(Singer.class) 明确指定接口,则会使用 JDK 动态代理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值