1. 创建ResolvableType
来源 | 方法 |
---|---|
类 | ResolvableType#forClass |
字段 | ResolvableType#forField |
方法参数 | ResolvableType#forMethodParameter |
方法返回值 | ResolvableType#forMethodReturnType |
构造方法参数 | ResolvableType#forConstructorParameter |
2. 使用ResolvableType解析泛型
类定义如下
interface RawBar<T> {
}
class ComponentBar implements RawBar<org.springframework.stereotype.Component> {
}
class StringBar implements RawBar<java.lang.String> {
}
使用ResolvableType#resolveGeneric
获取泛型
// 直接获取拿不到泛型, 必须向上转型为 { PropBar } 才能拿到
assertNull(ResolvableType.forClass(ComponentBar.class).resolveGeneric(0));
// 向上转型为 { PropBar }
assertEquals(RawBar.class, ResolvableType.forClass(ComponentBar.class).getSuperType().resolve());
// 获取具体的泛型: org.springframework.stereotype.Component
assertEquals(org.springframework.stereotype.Component.class,
ResolvableType.forClass(ComponentBar.class).getSuperType().resolveGeneric(0)
);
// 获取具体的泛型: java.lang.String
assertEquals(java.lang.String.class,
ResolvableType.forClass(StringBar.class).getSuperType().resolveGeneric(0)
);
org.springframework.core.ResolvableType#resolveGeneric
方法签名
@Nullable
public Class<?> resolveGeneric(int... indexes) {
return getGeneric(indexes).resolve();
}
假设有一个字段定义如下:
Map<String, Map<Integer, String>>
resolveGeneric(0) == String.class
resolveGeneric(1) == Map.class
resolveGeneric(1, 0) == Integer.class
resolveGeneric(1, 1) == String.class
resolveGeneric(1, 2) == null
resolveGeneric(2) == null
3. 配合ListableBeanFactory使用
在Spring的依赖注入中,如果给依赖类声明了泛型,Spring甚至可以精准匹配泛型再进行注入,其实就是使用了ResolvableType
// 定义
static class MockKeyValueTemplate<K, V> {
}
@Configuration
public class SomeConfiguration {
@Bean
public MockKeyValueTemplate<String, String> stringKeyValueTemplate() {
return new MockKeyValueTemplate<>();
}
@Bean
public MockKeyValueTemplate<String, Object> objectKeyValueTemplate() {
return new MockKeyValueTemplate<>();
}
@Bean
public Map<String, Map<String, Integer>> nestedMap() {
return new HashMap<>();
}
}
@Test
public void extra_raw_inject() {
// 1. 指定泛型为 MockKeyValueTemplate<String, String>
String[] names1 = beanFactory.getBeanNamesForType(
ResolvableType.forClassWithGenerics(MockKeyValueTemplate.class, String.class, String.class)
);
assertEquals(1, names1.length);
assertEquals("stringKeyValueTemplate", names1[0]);
// 2. 指定泛型为 MockKeyValueTemplate<String, Object>
String[] names2 = beanFactory.getBeanNamesForType(
ResolvableType.forClassWithGenerics(MockKeyValueTemplate.class, String.class, Object.class)
);
assertEquals(1, names2.length);
assertEquals("objectKeyValueTemplate", names2[0]);
// 3. 仅指定类型, 不指定泛型
String[] names3 = beanFactory.getBeanNamesForType(
ResolvableType.forClass(MockKeyValueTemplate.class)
);
assertEquals(2, names3.length);
assertEquals("stringKeyValueTemplate", names3[0]);
assertEquals("objectKeyValueTemplate", names3[1]);
// 4. 指定嵌套泛型: Map<String, Map<String, Integer>>
String[] names4 = beanFactory.getBeanNamesForType(
ResolvableType.forClassWithGenerics(
Map.class,
ResolvableType.forClass(String.class),
ResolvableType.forClassWithGenerics(Map.class, String.class, Integer.class)
)
);
assertEquals(1, names4.length);
assertEquals("nestedMap", names4[0]);
}