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");
			}
		}
	}
}

通过上述代码,我可以看到:

  1. 首先会调用unsatisfiedNonSimpleProperties()方法拿到可以进行依赖注入的属性;
  2. 循序可以进行依赖注入的属性;
  3. 调用containsBean()方法判断现有的Bean信息中是否包含要这个BeanName对应的对象;其实就是去单例池和beanDefinitionMap中寻找是否存在;
  4. 存在的话通过getBean()方法获取Bean对象,getBean()方法详情请移步至《Spring之Bean生命周期~获取Bean》;
  5. 将属性和对象的对应关系记录到pvs中;
  6. 调用registerDependentBean()方法记录关联关系;
  7. 回到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);
		}
	}
}

通过上述代码,我们可以看到:

  1. 首先会调用unsatisfiedNonSimpleProperties()方法拿到可以进行依赖注入的属性;
  2. 经一系列的逻辑判断,这里最终会调到resolveDependency()方法进行查询,resolveDependency()方法的详解请移步至《Spring之Bean生命周期~依赖注入(2)》;
  3. 找到要注入的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);
}

这个方法的作用是校验哪个属性可以进行依赖注入,通过上述代码我们可以看到:

  1. 拿到所有的属性进行循环;
  2. 首先判断这个属性有set方法;
  3. isExcludedFromDependencyCheck()方法的大致逻辑,Bean的全限定名不包含 $$ 且 属性类型不是要忽略的类型 且 属性类型没有实现要忽略的接口;
  4. 判断在实例化后方法中 没有给 这个属性赋值;
  5. 判断要注入的类型不是基本类型或者不是基本类型数组;
  6. 这里并没有校验属性是不是被static修饰的,因为@Bean(autowire = Autowire.BY_NAME)已经是不推荐的方式,这里没有深入研究,欢迎知道的大佬留言!
  7. 通过上述判断的属性是可以通过@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);
	}
}

通过上述代码我们可以看到:

  1. 首先调用canonicalName()方法拿到真正的BeanName;
  2. 然后记录依赖关系;
  • dependentBeanMap
    • 依赖的Bean的map。即key是被依赖的bean,(被注入的bean),value表示依赖的bean的集合;
  • dependenciesForBeanMap
    • bean的依赖。即key表示 被依赖的bean,value表示 依赖bean的集合。

回到autowireByName()方法
回到autowireByType()方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值