如何判断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
相关产品推荐
相关产品推荐

