我越来越频繁地使用新的
@Bean
Spring3中的配置样式,作为XML bean定义文件的更安全的类型替代。不过,这种类型的安全性有时会阻止您做应该是有效的事情,这是由于Java缺乏类型表示性和Spring范围代理。
一个完整的单元测试,它演示了下面的问题,但简单地说,我有一个类
ServiceBean
,实现接口
ServiceA
和
ServiceB
. 这个bean是一个作用域代理(在本例中是会话作用域)。我还有豆子
ClientA
和
ClientB
,注入类型为的对象
服务A
和
服务B
分别。
在SpringXML配置中,这没有问题。Spring为
服务bean
它实现了两个接口,并且都注入到客户机bean中。它都是反射的,运行时类型也很好。
试试这个
@豆
-尽管如此,风格还是有问题的。这是演示测试。
首先,服务:
public interface ServiceA {}
public interface ServiceB {}
public class ServiceBean implements ServiceA, ServiceB {}
现在,客户:
public class ClientA {
public ClientA(ServiceA service) {}
}
public class ClientB {
public ClientB(ServiceB service) {}
}
现在,SpringBean定义:
@Configuration
public class ScopedProxyConfig {
@Bean @Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
public ServiceBean services() {
return new ServiceBean();
}
@Bean
public ClientA clientA() {
return new ClientA(services());
}
@Bean
public ClientB clientB() {
return new ClientB(services());
}
}
最后,单元测试和支持上下文:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ScopedProxyTest {
private @Resource ClientA clientA;
private @Resource ClientB clientB;
public @Test void test() {
assertThat(clientA, is(notNullValue()));
assertThat(clientB, is(notNullValue()));
}
}
<beans>
<context:annotation-config/>
<bean class="test.ScopedProxyConfig"/>
</beans>
(为了清晰起见,省略了XML名称空间)。
所有这些都很好地编译。但是,运行测试,您会得到一个类型转换运行时异常:
原因:java.lang.ClassCastException:$proxy11无法强制转换为test.serviceBean
在test.scopedProxyConfig$$EnhancerbyCGlib$$d293ecc3.services()上
在StestDePro CONFIG.cliTon(SeopDeXOXCONFIG.java:26)
我不清楚这究竟告诉了我什么,但它似乎是JDK代理(实现
服务A
和
服务B
)以及
服务bean
对象。
我试过用仿制药来变聪明:
@Bean @Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
public <T extends ServiceA & ServiceB> T services() {
return (T)new ServiceBean();
}
但它甚至不能编译。
我想这不是一个特别奇特的情况,我以前也遇到过。在过去,解决方法是
TARGET_CLASS
代理而不是接口代理,但这不是我这里的一个选项。
有人能想出怎么做这个吗?