更进一步
VMware 提供培训和认证,以加速您的进步。
了解更多随着 Spring Framework 4.0 的最新 RC2 发布;以及 GA 将在年底前发布,这里简单介绍一下一些应该可以改善您使用 Java 泛型类型的工作的变化。
Spring 在很长一段时间内都拥有相当不错的 Java 泛型支持。例如,使用 3.2 版本,您可以轻松地使用 @Autowired
注解将特定类型的所有 bean 注入到泛型 List
中
@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>
,您将收到以下异常
"未定义 [Store] 类型的符合条件的 bean:预期单个匹配 bean,但找到 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 发布候选版本,可在我们的 里程碑存储库 中找到。