我已經作出越來越重使用新@Bean
配置風格的春季3,爲更多的類型安全的替代XML bean定義文件。但偶爾,由於Java缺乏類型表現力和Spring範圍代理,這種類型安全性可能會阻止你做有效的事情。春@Bean CONFIGS和Java多態性
演示此問題的完整單元測試如下,但簡要說明我有一個類ServiceBean
,它實現了接口ServiceA
和ServiceB
。這個bean是一個作用域代理(在這種情況下是會話作用域)。我也有豆ClientA
和ClientB
,這是與ServiceA
類型和ServiceB
的對象分別注入。
在Spring XML配置,有一個與這個沒有問題。 Spring爲ServiceBean
生成一個JDK代理,該代理實現了兩個接口,並且兩者都被注入到客戶端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) {}
}
現在,Spring的bean定義:
@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.ScopedProxyConfig $$ EnhancerByCGLIB被轉換爲test.ServiceBean $$ d293ecc3
所致。服務() 在test.ScopedProxyConfig.clientA(ScopedProxyConfig.java:26)
這不是很清楚,我到底是什麼,這是告訴我,但它似乎是JDK代理之間的衝突(實現和ServiceBean
對象。
我已經試過越來越狡猾泛型:
@Bean @Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
public <T extends ServiceA & ServiceB> T services() {
return (T)new ServiceBean();
}
但是,這並不編譯。
這不是一個特別奇特的情況,我想,我之前幾次碰到的吧。在過去,解決方法是使用TARGET_CLASS
代理而不是接口代理,但這不是我的選擇。
任何人都可以弄清楚如何使這項工作?
BTW:我沒有看到使用java配置風格的好處。如果你使用STS,那麼XML風格使用起來會更加舒適,Spring構建器將比java編譯器能夠分析和報告更多的錯誤。 – 2010-10-27 13:41:00
@seanizer:我明白你在說什麼,這是個人喜好的問題。兩者都是有效的。 – skaffman 2010-10-27 13:54:07
爲真。並且我知道spring多年來一直是XML地獄,但是用瞭解* XML的IDE,它實際上非常有趣並且非常高效。 – 2010-10-27 14:00:10