You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断Spring中Autowired注入的代理实例是否为目标实现类?

穿透Spring代理获取真实实现类的方法

因为你的Connector实现类使用了ScopedProxyMode.INTERFACES,Spring会生成JDK动态代理对象,导致直接断言类类型失败。以下是几种可靠的解决方案:

方法一:使用Spring自带的AopUtils工具类(推荐)

Spring提供了专门的工具类来处理代理对象,无需手动操作反射:

import org.springframework.aop.support.AopUtils;
import static org.assertj.core.api.Assertions.assertThat;

// 在测试方法中获取真实目标类并断言
Class<?> actualClass = AopUtils.getTargetClass(classUnderTest);
assertThat(actualClass).isEqualTo(ConnectorV2.class);

AopUtils.getTargetClass()会自动识别代理对象,直接返回被代理的真实类;如果传入的不是代理对象,会直接返回当前类的Class对象,兼容性很强。

方法二:手动拆解JDK动态代理(仅作原理参考)

如果不想依赖Spring的工具类,可以通过反射直接获取代理的目标对象:

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import org.springframework.aop.framework.AdvisedSupport;
import static org.assertj.core.api.Assertions.assertThat;

if (Proxy.isProxyClass(classUnderTest.getClass())) {
    try {
        // 获取JDK代理的InvocationHandler
        Field hField = classUnderTest.getClass().getDeclaredField("h");
        hField.setAccessible(true);
        Object handler = hField.get(classUnderTest);
        
        // 从Spring的代理处理器中获取真实目标对象
        if (handler instanceof AdvisedSupport) {
            AdvisedSupport advised = (AdvisedSupport) handler;
            Object targetObject = advised.getTargetSource().getTarget();
            assertThat(targetObject.getClass()).isEqualTo(ConnectorV2.class);
        }
    } catch (Exception e) {
        throw new RuntimeException("无法从代理对象中获取真实实例", e);
    }
}

这种方法需要处理反射异常,且只适用于JDK动态代理场景,通用性不如AopUtils。

额外优化:直接注入实现类(测试场景可选)

如果你的测试场景允许,可以直接注入具体的实现类而非接口,避免代理类型判断:

@Autowired
@Qualifier("V2")
private ConnectorV2 classUnderTest;

// 直接断言即可,无需处理代理
assertThat(classUnderTest).isInstanceOf(ConnectorV2.class);

不过这种方式依赖于Spring能够直接找到对应的实现类Bean,仅适用于测试环境中明确需要指定实现类的场景。

内容的提问来源于stack exchange,提问作者Florian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:43:07