10、Spring之Bean生命周期~依赖注入(1)
Spring自带注入方式
通过《Spring之Bean生命周期~依赖注入(总)》,我们知道Spring在属性填充时,会先处理@Bean(autowire = Autowire.BY_NAME)或者@Bean(autowire = Autowire.BY_type)方式设置自动注入,废话不多说,上代码:
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
*
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 实例化之后,属性设置之前
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 执行 InstantiationAwareBeanPostProcessors接口的postProcessAfterInstantiation()方法 根据返回值判断是否跳过属性填充
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
/**
*
* 处理spring自带的依赖注入的功能 @Bean(autowire = Autowire.BY_NAME)
*
* */
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// MutablePropertyValues是PropertyValues具体的实现类
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
这里我们重点解析@Bean(autowire = Autowire.BY_NAME)方式的依赖注入,如果想了解其他方式的依赖注入请移步至《Spring之Bean生命周期~依赖注入(总)》;我们现在来分析autowireByName()方法和autowireByType()方法;
autowireByName()方法
autowireByName()方法详解
/**
* Fill in any missing property values with references to
* other beans in this factory if autowire is set to "byName".
*
* @param beanName the name of the bean we're wiring up.
* Useful for debugging messages; not used functionally.
* @param mbd bean definition to update through autowiring
* @param bw the BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 当前Bean中能进行自动注入的属性名
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍历每个属性名,并去获取Bean对象,并设置到pvs中
for (String propertyName : propertyNames) {
// 根据beanName 去单例池、beanDefinitionMap中寻找
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
// 记录一下propertyName对应的Bean被beanName给依赖了
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
} else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
通过上述代码,我可以看到:
- 首先会调用unsatisfiedNonSimpleProperties()方法拿到可以进行依赖注入的属性;
- 循序可以进行依赖注入的属性;
- 调用containsBean()方法判断现有的Bean信息中是否包含要这个BeanName对应的对象;其实就是去单例池和beanDefinitionMap中寻找是否存在;
- 存在的话通过getBean()方法获取Bean对象,getBean()方法详情请移步至《Spring之Bean生命周期~获取Bean》;
- 将属性和对象的对应关系记录到pvs中;
- 调用registerDependentBean()方法记录关联关系;
- 回到populateBean()方法;
autowireByType()方法
autowireByType()方法详解
/**
* Abstract method defining "autowire by type" (bean properties by type) behavior.
* <p>This is like PicoContainer default, in which there must be exactly one bean
* of the property type in the bean factory. This makes bean factories simple to
* configure for small namespaces, but doesn't work as well as standard Spring
* behavior for bigger applications.
*
* @param beanName the name of the bean to autowire by type
* @param mbd the merged bean definition to update through autowiring
* @param bw the BeanWrapper from which we can obtain information about the bean
* @param pvs the PropertyValues to register wired objects with
*/
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 当前Bean中能进行自动注入的属性名
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
// eager表示立即初始化,表示在根据类型查找Bean时,允不允许进行Bean的创建,如果当前bean实现了PriorityOrdered,那么则不允许
// 为什么不允许,因为我自己是PriorityOrdered,是优先级最高的,不能有比我创建得更早的
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 根据类型找到的结果
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
// 记录依赖关系
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
通过上述代码,我们可以看到:
- 首先会调用unsatisfiedNonSimpleProperties()方法拿到可以进行依赖注入的属性;
- 经一系列的逻辑判断,这里最终会调到resolveDependency()方法进行查询,resolveDependency()方法的详解请移步至《Spring之Bean生命周期~依赖注入(2)》;
- 找到要注入的Bean对象之后会调用registerDependentBean()方法,记录依赖关系;
unsatisfiedNonSimpleProperties()方法
unsatisfiedNonSimpleProperties()方法详解
/**
* Return an array of non-simple bean properties that are unsatisfied.
* These are probably unsatisfied references to other beans in the
* factory. Does not include simple properties like primitives or Strings.
*
* @param mbd the merged bean definition the bean was created with
* @param bw the BeanWrapper the bean was created with
* @return an array of bean property names
* @see org.springframework.beans.BeanUtils#isSimpleProperty
*/
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
// 什么样的属性能进行自动注入?
// 1.该属性有对应的set方法
// 2.没有在ignoredDependencyTypes中
// 3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
// 4.属性类型不是简单类型,比如int、Integer、int[]
for (PropertyDescriptor pd : pds) {
//属性有set方法
boolean b = pd.getWriteMethod() != null;
// Bean的全限定名不包含 $$ 且 属性类型不是要忽略的类型 且 属性类型没有实现要忽略的接口
boolean b1 = !isExcludedFromDependencyCheck(pd);
// 在实例化后方法中 没有给 这个属性赋值
boolean b2 = !pvs.contains(pd.getName());
// 要注入的类型不是基本类型 如果是数组
boolean b3 = !BeanUtils.isSimpleProperty(pd.getPropertyType());
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
这个方法的作用是校验哪个属性可以进行依赖注入,通过上述代码我们可以看到:
- 拿到所有的属性进行循环;
- 首先判断这个属性有set方法;
- isExcludedFromDependencyCheck()方法的大致逻辑,Bean的全限定名不包含 $$ 且 属性类型不是要忽略的类型 且 属性类型没有实现要忽略的接口;
- 判断在实例化后方法中 没有给 这个属性赋值;
- 判断要注入的类型不是基本类型或者不是基本类型数组;
- 这里并没有校验属性是不是被static修饰的,因为@Bean(autowire = Autowire.BY_NAME)已经是不推荐的方式,这里没有深入研究,欢迎知道的大佬留言!
- 通过上述判断的属性是可以通过@Bean(autowire = Autowire.BY_NAME)的方式注入进去;
回到autowireByName()方法;
回到autowireByType()方法;
registerDependentBean()方法
registerDependentBean()方法详解
/**
* Register a dependent bean for the given bean,
* to be destroyed before the given bean is destroyed.
* @param beanName the name of the bean
* @param dependentBeanName the name of the dependent bean
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
通过上述代码我们可以看到:
- 首先调用canonicalName()方法拿到真正的BeanName;
- 然后记录依赖关系;
- dependentBeanMap
- 依赖的Bean的map。即key是被依赖的bean,(被注入的bean),value表示依赖的bean的集合;
- dependenciesForBeanMap
- bean的依赖。即key表示 被依赖的bean,value表示 依赖bean的集合。