Spring实现泛型注入的示例详解
作者:默念x
1.Spring泛型注入
创建一个抽象泛型类BaseDao,有参数化类型T
public abstract class BaseDao<T> { public abstract void eat(); }
每种动物有不同的行为,猫、狗
public class Cat { } public class Dog { }
分别继承BaseDao实现不同的行为
@Repository public class CatDao extends BaseDao<Cat> { @Override public void eat() { System.out.println("cat eat...."); } }
@Repository public class DogDao extends BaseDao<Dog> { @Override public void eat() { System.out.println("dog eat...."); } }
接着创建一个抽象业务类,也有参数化类型T。
注意:此处不能使用@Resource注入,会找到多个BaseDao类型的bean,无法确认注入哪一个bean会报错
需要使用@Autowired注入,它有根据泛型参数匹配的逻辑,会一个个去匹配
public abstract class BaseService<T> { @Autowired private BaseDao<T> baseDao; protected void eat() { baseDao.eat(); } }
子类继承BaseService指定参数化类型实现注入相应的BaseDao
@Service public class CatService extends BaseService<Cat> { }
@Service public class DogService extends BaseService<Dog> { }
代码目录
测试
@Configuration @ComponentScan(value = "com.monian.test.generic") public class GenericConfig { }
public class GenericTests { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); applicationContext.register(GenericConfig.class); applicationContext.refresh(); DogService dogService = applicationContext.getBean(DogService.class); CatService catService = applicationContext.getBean(CatService.class); dogService.eat(); catService.eat(); } }
结果输出,成功注入相应的BaseDao
2. 关于java泛型有四种Type
GenericArrayType泛型数组类型
public class GenericArrayTypeTest { public static class TestClass<S> { // 泛型数组 private List<String>[] lists; // 泛型数组 private S[] ss; private String[] s; } public static void main(String[] args) { Class cl = TestClass.class; for (Field field : cl.getDeclaredFields()) { System.out.println("filed's name:" + field.getName()); Type genericType = field.getGenericType(); System.out.println("Is it genericArrayType:" + (genericType instanceof GenericArrayType)); if (genericType instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) genericType; System.out.println(genericArrayType.getTypeName()); Type genericComponentType = genericArrayType.getGenericComponentType(); System.out.println(genericComponentType); } System.out.println(); } } }
result:
filed's name:lists
Is it genericArrayType:true
java.util.List<java.lang.String>[]
java.util.List<java.lang.String>
filed's name:ss
Is it genericArrayType:true
S[]
S
filed's name:s
Is it genericArrayType:false
ParameterizedType参数化类型
public class ParameterizedTypeTest { public static abstract class Test<T> { public abstract void test(T t); } public static class TestClass<T extends Number> extends Test<Integer> { private List<T> tList; private List<? extends Number> list; private Map<String, Integer> map; @Override public void test(Integer o) { } } public static void main(String[] args) { TestClass<Integer> tt = new TestClass<>(); Class cl = tt.getClass(); Type genericSuperclass = cl.getGenericSuperclass(); assert genericSuperclass instanceof ParameterizedType; ParameterizedType parameterizedType1 = (ParameterizedType) genericSuperclass; System.out.println(parameterizedType1.getActualTypeArguments()[0]); for (Field field : cl.getDeclaredFields()) { System.out.println("field's name:" + field.getName()); Type genericType = field.getGenericType(); System.out.println("Is it ParameterizedType:" + (genericType instanceof ParameterizedType)); if (genericType instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) genericType; for (Type type : parameterizedType.getActualTypeArguments()) { System.out.println("actualType:" + type); System.out.println(type.getTypeName()); } } System.out.println(); } } }
result:
class java.lang.Integer
field's name:tList
Is it ParameterizedType:true
actualType:T
T
field's name:list
Is it ParameterizedType:true
actualType:? extends java.lang.Number
? extends java.lang.Number
field's name:map
Is it ParameterizedType:true
actualType:class java.lang.String
java.lang.String
actualType:class java.lang.Integer
java.lang.Integer
TypeVariable 类型变量
public class TypeVariableTest { public static class TestClass<S extends Number, T> { private Map<S, T> map; } public static void main(String[] args) throws Exception { Class cl = TestClass.class; Field field = cl.getDeclaredField("map"); Type genericType = field.getGenericType(); ParameterizedType parameterizedType = (ParameterizedType) genericType; for (Type type : parameterizedType.getActualTypeArguments()) { TypeVariable typeVariable = (TypeVariable) type; // 类型变量名 System.out.println(typeVariable.getName()); // 变量上边界 Type[] bounds = typeVariable.getBounds(); System.out.println(Arrays.toString(bounds)); } } }
result:
S
[class java.lang.Number]
T
[class java.lang.Object]
WildcardType 通配符类型
public class WildcardTypeTest { public static class TestClass { private List<? extends Number> lists; private Set<?> sets; private Map<? extends Number, ? super String> map; } public static void main(String[] args) { Class cl = TestClass.class; for (Field field : cl.getDeclaredFields()) { System.out.println("filed's name:" + field.getName()); Type genericType = field.getGenericType(); ParameterizedType parameterizedType = (ParameterizedType) genericType; for (Type type : parameterizedType.getActualTypeArguments()) { // 通配符类型 WildcardType wildcardType = (WildcardType) type; System.out.println(wildcardType.getTypeName()); // 上边界 System.out.println("上边界" + Arrays.toString(wildcardType.getUpperBounds())); // 下边界 System.out.println("下边界" + Arrays.toString(wildcardType.getLowerBounds())); } System.out.println(); } } }
result:
filed's name:lists
? extends java.lang.Number
上边界[class java.lang.Number]
下边界[]
filed's name:sets
?
上边界[class java.lang.Object]
下边界[]
filed's name:map
? extends java.lang.Number
上边界[class java.lang.Number]
下边界[]
? super java.lang.String
上边界[class java.lang.Object]
下边界[class java.lang.String]
注:spring对泛型的解析主要是在ResolvableType类,掌握上述的基本知识后可以去阅读下相关源码
到此这篇关于Spring实现泛型注入的示例详解的文章就介绍到这了,更多相关Spring泛型注入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!