前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring源码学习(三)炒鸡丁与populateBean没区别

Spring源码学习(三)炒鸡丁与populateBean没区别

作者头像
温安适
发布2019-10-03 14:04:18
9980
发布2019-10-03 14:04:18
举报
文章被收录于专栏:温安适的blog温安适的blog

逻辑说明

populateBean的流程

炒鸡丁的流程

1.执行InstantiationAwareBeanPostProcessor 的postProcessAfterInstantiation (在设置属性前去修改Bean的状态,也可以控制是否继续填充Bean)

作为一个已婚男人炒菜之前,请示老婆,这很重要。 我:“我炒宫爆鸡丁了,有特殊要求吗?” 老婆大人:“没有要求,炒吧”。

2.注入属性到PropertyValues中(autowireByName/autowireByType)

初步准备食材 准备鸡肉,郫县豆瓣酱,花生米,黄瓜

3.执行InstantiationAwareBeanPostProcessor的postProcessPropertyValues, 对解析完但未设置的属性再进行处理

切菜 鸡肉切丁,黄瓜切小块。

4.对dependency-check属性的支持,默认是不校验

5.将PropertyValues中的属性值设置到BeanWrapper中

下锅,炒熟出锅

autowirebyType的大致逻辑

看了源码总结如下:

  1. 不处理简单属性,即不处理:Enum,CharSequence,Number,Date,URI,Locale等。(具体可以查看org.springframework.beans.BeanUtils#isSimpleProperty这个方法。)
  2. 不对Object类型的属性进行自动注入, 没有意义,技术无法实现
  3. 解析依赖resolveDependency并设置到pvs中
  4. registerDependentBean 注册当前依赖。

autowiredByType的源码注释

代码语言:javascript
复制
/**
	 * 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.
	 * 类似PicoContainer(非常轻量级的Ioc容器),beanFactory中一个属性类型必须有一个确切对应的bean
	 * bean工厂很容易配置小的命名空间.
	 * @param beanName the name of the bean to autowire by type  需要按类型注入的BeanName
	 * @param mbd the merged bean definition to update through autowiring   合并后的BeanDefinition
	 * @param bw the BeanWrapper from which we can obtain information about the bean  BeanWrapper对象
	 * @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;
		}
		//获取需要 注入的 非简单类型
		/**
		 * 简单类型,详见
		 * @see org.springframework.beans.BeanUtils#isSimpleProperty
		 */
		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		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.
				// 不对Object类型的属性进行自动注入, 没有意义,技术无法实现
				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.
					// 假如实现了prioritized post-processor ,在进行类型匹配时,是不允许,eager初始化(热加载)的
					boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
					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);
			}
		}
	}

下回写resolveDependency的逻辑。

一图胜千言

源码注释

代码语言:javascript
复制
	/**
	 * Populate the bean instance in the given BeanWrapper with the property values
	 * from the bean definition.
	 * 填充bean的属性
	 * @param beanName the name of the bean   bean的名称
	 * @param mbd the bean definition for the bean 合并后的Bean的定义
	 * @param bw the BeanWrapper with bean instance   beanWrapper的对象
	 */
	@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.
				// 跳过没有属性,null实例
				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.
		//给任何InstantiationWareBeanPostProcessors在设置属性之前修改bean的状态的机会。
		// 例如,这可用于支持属性注入
		boolean continueWithPropertyPopulation = true;
		//InstantiationWareBeanPostProcessors  可以控制是否继续填充bean
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
				//根据名称自动注入
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == 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) {
			//有InstantiationAwareBeanPostProcessors 对象
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			//检查依赖Dependency-check
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			//将属性值设置到Bean中
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 逻辑说明
  • autowirebyType的大致逻辑
  • 一图胜千言
  • 源码注释
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档