@Autowired注解(二)
本文主要测试了两种情况的依赖注入。分别是泛型以及配合@Qulifier注解的注入。
代码如下:
@Configuration
public class TestAutowired {public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestAutowired.class);DefaultListableBeanFactory factory = context.getDefaultListableBeanFactory();//1.解析泛型类型的依赖注入testGeneric(factory);//2.解析带有@Qualifier的依赖注入testQulifier(factory);}private static void testGeneric(DefaultListableBeanFactory factory) throws NoSuchFieldException {DependencyDescriptor descriptor = new DependencyDescriptor(Target.class.getDeclaredField("studentDao"), true);Class<?> type = descriptor.getDependencyType();ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();resolver.setBeanFactory(factory);for (String name : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, type)) {BeanDefinition definition = factory.getMergedBeanDefinition(name);if (resolver.isAutowireCandidate(new BeanDefinitionHolder(definition, name), descriptor)) {System.out.println(name);System.out.println(descriptor.resolveCandidate(name,type,factory));}}}private static void testQulifier(DefaultListableBeanFactory factory) throws NoSuchFieldException {DependencyDescriptor descriptor2 = new DependencyDescriptor(Target.class.getDeclaredField("service"), true);Class<?> type = descriptor2.getDependencyType();ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();resolver.setBeanFactory(factory);for (String name : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, type)) {BeanDefinition definition = factory.getMergedBeanDefinition(name);if (resolver.isAutowireCandidate(new BeanDefinitionHolder(definition, name), descriptor2)) {System.out.println(name);System.out.println(descriptor2.resolveCandidate(name,type,factory));}}}@Componentstatic class Target {@Autowired private Service[] serviceArray;@Autowired private List<Service> serviceList;@Autowiredprivate Dao<Student> studentDao;@Autowired @Qualifier("service2") private Service service;}interface Dao<T> {T get();}@Component("dao1")static class Student implements Dao<Student>{private String name;@Overridepublic Student get() {return new Student();}}@Component("dao2")static class Teacher implements Dao<Teacher>{private String name;@Overridepublic Teacher get() {return new Teacher();}}interface Service{}@Component("service1")static class Service1 implements Service{private String name;}@Component("service2")static class Service2 implements Service{private String name;}@Component("service3")static class Service3 implements Service{private String name;}}
一.解析泛型类型的依赖注入
如果@Autowired注入的类是一个泛型,Spring该如何查找?有两个接口都实现了Dao。这个时候只能拿到泛型里面的类型去判断。下面模拟的是框架的实现思路。
1. 创建目标字段的依赖描述符
DependencyDescriptor descriptor2 = new DependencyDescriptor(Target.class.getDeclaredField("service"), true);
2. 获取依赖类型
3. 配置自动装配候选解析器(ContextAnnotationAutowireCandidateResolver)
4. 遍历所有匹配类型的Bean定义,筛选出符合条件的自动装配候选类
5. 输出候选Bean的名称和实例
二.解析带有@Qualifier的依赖注入
如果@Autowired注入的类是一个接口,又有三个类实现了该接口。只根据接口类型还是不能确定类,只能配合@Qualifier注解根据类的名字去确认。
所以我们首先通过DependencyDescriptor创建对Target类中service字段的依赖描述,该字段被@Autowired和@Qualifier("service2")注解修饰。接着获取该字段的依赖类型(即Service接口),并配置ContextAnnotationAutowireCandidateResolver自动装配候选解析器。然后使用BeanFactoryUtils.beanNamesForTypeIncludingAncestors方法查找所有类型为Service的Bean名称,遍历这些Bean定义,通过解析器的isAutowireCandidate方法判断哪些Bean适合作为该依赖的候选者(由于@Qualifier注解的存在,只有名为"service2"的Bean会通过筛选)。最后输出选中的Bean名称以及通过resolveCandidate方法解析出的Bean实例。整个过程演示了Spring如何结合类型匹配和@Qualifier注解来精确解析和注入特定的Bean实例。