领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多随着最近发布的 Spring Framework 4.0 RC2 版本,以及预计在年底发布的 GA 版本,这里提供了一些更改的简要介绍,如果您使用 Java 泛型类型,这些更改应该可以改善您的工作体验。
Spring 一直以来都对 Java 泛型提供了良好的支持。例如,在 3.2 版本中,您可以轻松地将特定类型的全部 Bean 注入到泛型 List
中,只需使用 @Autowired
注解即可。
@Autowired
private List<MyType> beans;
// all beans that extends MyType will be injected
Spring 的转换服务、绑定系统和 Web MVC 框架都“了解”泛型,并且还有一些方便的 GenericCollectionTypeResolver
和 GenericTypeResolver
实用程序类,您可以在自己的代码中使用它们。
不幸的是,Spring 早期版本的一个问题是,您无法将泛型用作限定符。例如,您可能会有这样的配置
@Configuration
public class MyConfiguration {
@Bean
public Store<String> stringStore() {
return new StringStore();
}
@Bean
public Store<Integer> integerStore() {
return new IntegerStore();
}
}
如果您尝试使用 Spring 3.2 @Autowire
Store<String>
,则会收到以下异常
"No qualifying bean of type [Store] is defined: expected single matching bean but found 2: stringStore, integerStore"
这里 Spring 告诉您它找到了两个 Store
的实现,并且无法区分它们。
一种可能的解决方法是直接使用具体的 StringStore
和 IntegerStore
类,而不是使用泛型 Store
接口。但是,如果您的实现类是“私有的”,或者如果它们是使用代理动态创建的(例如,在 Spring Data Repository
的情况下),则可能无法这样做。
另一种选择是在 @Bean
方法和 @Autowire
字段上都使用 @Qualifier
注解,为 Spring 提供有关您实际想要哪个 Bean 的提示。
幸运的是,从 Spring Framework 4.0 开始,此类解决方法将不再需要。Spring 4.0 将自动将泛型视为一种 @Qualifier
。例如
@Autowired
private Store<String> s1; // Injects the stringStore bean
@Autowired
private Store<Integer> s2; // Injects the integerStore bean
您甚至可以在注入到列表时使用嵌套泛型
// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@Autowired
private List<Store<Integer>> s;
在幕后,新的 ResolvableType 类提供了实际使用泛型类型的逻辑。您可以自己使用它来轻松导航和解析类型信息。ResolvableType
上的大多数方法本身都会返回一个 ResolvableType
,例如
// Assuming 'field' refers to 's' above
ResolvableType t1 = ResolvableType.forField(field); // List<Store<Integer>>
ResolvableType t2 = t1.getGeneric(); // Store<Integer>
ResolvableType t3 = t2.getGeneric(); // Integer
Class<?> c = t3.resolve(); // Integer.class
// or more succinctly
Class<?> c = ResolvableType.forField(field).resolveGeneric(0, 0);
以下是一个示例,它展示了如果您获得超类型或实现的接口,如何保留泛型信息。
// Assuming 'm' refers to a method that returns MultiValueMap<Integer, String>
ResolvableType t1 = ResolvableType.forMethodReturnType(m); // MultiValueMap<Integer, String>
ResolvableType t2 = t1.asMap(); // Map<Integer, List<String>>
ResolvableType t3 = t2.getGeneric(1); // List<String>
ResolvableType t4 = t3.getGeneric(); // String
Class<?> c = t4.resolve(); // String.class
// or more succinctly
Class<?> c = ResolvableType.forMethodReturnType(m).asMap().resolveGeneric(1, 0);
Spring 4.0 将于 12 月 12 日发布,但如果您想立即体验泛型支持,您可以尝试最新的 4.0 发布候选版本,该版本可在我们的 里程碑存储库 中获得。