@Autoeired是通过bean的后置处理器进行解析
什么是@Autowired表示某个属性是否需要进行依赖注入,可以写在属性和方法上,注解中的required属性默认为true,表示如果没有对象可以注入给属性则抛异常
核心代码:postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//1.获取当前类中标注了@Autowired的成员变量和方法的参数封装在metadata对象里
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//2.利用反射赋值
metadata.inject(bean, beanName, pvs);
return pvs;
} catch (BeanCreationException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
}
}
postProcessProperties()方法的处理流程:
1.调用findAutowiringMetadata()方法,尝试从缓存injectionMetadataCache中获取对应的注入元信息,如果缓存不存在,将会执行buildAutowiringMetadata()获取;
2.循环InjectionMetadata的injectedElements属性,挨个调用InjectionMetadata.InjectedElement.inject方法,通过反射方式设置属性的值
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//metadata中的数据放在集合中
Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
Collection<Injectio
nMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
if (!((Collection)elementsToIterate).isEmpty()) {
Iterator var6 = ((Collection)elementsToIterate).iterator();
//遍历集合拿到标注了@AutoWired的成员变量和方法
while(var6.hasNext()) {
InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
//遍历调用内部类的方法完成属性赋值
element.inject(target, beanName, pvs);
}
}
}
1.当@Autowired写在属性上时:
@Autowired加在某个属性上,Spring在进行Bean的声明周期过程中,在属性填充这一步,会基于实例化出来的对象,该对象中加了@Autowired的属性自动给属性赋值
spring会根据属性的类型去spring容器中找出该类型的所有的Bean对象,如果找出来多个,则根据属性的名字从多个中确定一个。如果required属性为true,并且根据属性信息找不到对象,则直接抛出异常,
findAutowiringMetadata()方法返回metadata对象
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//获取当前bean的名称
String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
//在缓存中查找是否有当前类的信息
InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized(this.injectionMetadataCache) {
metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//调用此方法解析当前类,获得所有标注@AutoWired的字段 并存入metada中
metadata = this.buildAutowiringMetadata(clazz);
//存入缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
//返回得到@AutoWired的字段的metadata
return metadata;
}
2.当@Autowired写在方法上时
当@Autowired写在方法上时,Spring在Bean生命周期的属性的填充阶段,会根据方法的参数类型、参数名字从spring容器中找到对象当做方法入参,通过反射自动调用该方法
3.当@Autowired写在构造方法上时:
@Autowired加在构造方法时,Spring会在推断构造方法阶段选择该方法来进行实例化,在反射调用构造方法之前,会先根据构造方法的方法参数类型、参数名从Spring容器中找到Bean对象,当做构造方法的入参