spring源码之@Autowired属性注入

注入现象

当我们在属性上面加上 @Autowired的时候,spring就要根据Type来注入实例了,那么到底会找哪个实例的如果有多个怎么办? 今天就来实验一下

多接口注入

当注入的属性接口下有多个实现。这个时候运行的话是


public class ModelTest {
	@Test
	public void defaultModel(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.scan("com.spring.inject");
		context.refresh();
		I i = context.getBean(F.class).getI();
		System.out.println("i==="+i);
	}
}

@Component
public class F {
	@Autowired
	I i;
	public I getI() {
		return i;
	}
}

public interface I {
}

@Component("a")
public class Ia implements I{
}

@Component("b")
public class Ib implements I{
}

报错如下:找到了多个实现接口类,不知道用哪个。
在这里插入图片描述

多接口制定名称注入

如果把F类中的属性名称指定。

@Component
public class F {
	@Autowired
	I a;
	public I getI() {
		return a;
	}
}

成功运行,注入了指定名称的Ia实例。
在这里插入图片描述

现象总结

Autowired是通过Type来寻找类的,如果找到多个实现,则再按照名称来寻找指定的类,最终确定一个类,注入到属性中。
下面我们来通过源码验证一下这个结论。

源码

点击Autowired进入该类,发现没有什么东西;但是类头部的注解让我们跳转这个类AutowiredAnnotationBeanPostProcessor,这明显就是Autowired的处理器。
spring源码之@Autowired属性注入_第1张图片
这个类中有两个主要方法
AutowiredFieldElement和AutowiredMethodElement,意思是Autowired注解是在属性上和方法上。我们要看得肯定是第一个AutowiredMethodElement.inject()这个方法
红框的上半部分是缓存,如果解析过一次的话会走上面。我们主要看红框下半部分resolveMethodArguments方法。看这个方法名字就很清晰了,解析属性值,解析什么属性值呢,肯定是加了Autowired注解的属性。

spring源码之@Autowired属性注入_第2张图片

DependencyDescriptor是一个依赖描述器,比如刚才例子中,会说明是在F类中的I属性上有这个Autowired注释,属性的名字是a等等数据。
然后通过这个依赖描述器,到beanFactory.resolveDependency()这个方法中进行处理。
spring源码之@Autowired属性注入_第3张图片
这个方法中也有好多内容,现在可以先不用管,后面会慢慢分析那些懒加载之类的东西。只需要看doResolveDependency()这个方法。
spring源码之@Autowired属性注入_第4张图片
这个方法中的这一行比较重要,是获取到多个属性的多个Bean之后直接注入到属性当中,不再按照名称筛选出单个。这也就是为什么当我们在List或者Map属性上加Autowired注释的时候,可以直接将接口下的所有实现类注入的原理。核心就是这个方法resolveMultipleBeans()。
这个方法中也简单就是判断一下Autowired注释下的属性是否是Array或者Map等数组集合类型,如果是的话,就将查询到的多个Bean直接塞进去返回,如果不是的话就返回一个空。
这里一旦返回一个空,就证明这个Autowired注释下的属性只能注入一个Bean。
spring源码之@Autowired属性注入_第5张图片
顺着刚才的代码继续往下看,findAutowireCandidates()这个方法就是按照注释下的属性查找Bean。通过例子来解释的话,就是按照“I”这个类,查询到下面的两个实现类“Ia”和“Ib”。如果没有查询到的话就返回一个null。
下面还有一个判断如果查询到多个的话,就要进行筛选了。主要是通过这个方法determineAutowireCandidate()
spring源码之@Autowired属性注入_第6张图片
可以看到,这个方法里面有个for循环,很简单嘛,意思就是通过属性的名字筛选多个Bean,如果名称一样的话,就返回对应的Bean。只要遍历到一个相同的就直接返回,因为在Spring中不可能有多个Bean的名字相同。
spring源码之@Autowired属性注入_第7张图片

源码总结

  1. 当属性上有Autowired注解的时候
  2. 会先判断属性是否可以注入多个Bean,如果可以的话,直接将找到的多个注入进集合中
  3. 如果不可以的话,判断找到一个还是多个
  4. 找到一个Bean则直接返回
  5. 找到数量大于1个的话,将多个Bean遍历,与属性名称进行对比,一致则直接返回。

你可能感兴趣的:(spring源码,java,spring,autowired,源码)