spring源码之bean的属性填充populateBean方法解读

目录

  • 前言
  • 测试代码
    • `Java` 实体
    • `xml` 配置文件
    • 测试类
  • `populateBean()` 源码概览
  • `populateBean()` 源码详解
    • 自动装配
      • 自动装配之 `autowireByName()`
      • 自动装配之 `autowireByType()`
    • `applyPropertyValues()` 方法
  • 关于自动装配方式
  • `populateBean()` 方法小结

前言

这篇文章是 IOC 容器初始化启动时,抽象类 AbstractAutowireCapableBeanFactorydoCreateBean() 方法里面的 populateBean() 方法,它是进行 bean 的属性数据填充注入的方法

阅读本篇文章,同时可以参考阅读 spring源码之getBean(获取 bean)方法解读(二) 和 spring aop代理对象的产生(一) 这两篇文章的 doCreateBean() 方法

测试代码

Java 实体

public class Teacher {
     

    private Student student;

    public Teacher() {
     
        System.out.println("Teacher 的无参构造器被调用了");
    }

    public Teacher(Student student) {
     
        System.out.println("Teacher 的有参构造器被调用了");
        this.student = student;
    }

    public void echo() {
     
        System.out.println("I'm a student : " + student);
    }

    public Student getStudent() {
     
        return student;
    }

    public void setStudent(Student student) {
     
        this.student = student;
    }

    @Override
    public String toString() {
     
        return "Teacher{" +
                "student=" + student +
                '}';
    }
}


public class Student {
     

    private String name;

    public Student() {
     
        System.out.println("Student 的无参构造器被调用了");
    }

    public Student(String name) {
     
        System.out.println("Student 的有参构造器被调用了");
        this.name = name;
    }

    public String getName() {
     
        return name;
    }

    public void setName(String name) {
     
        this.name = name;
    }

    @Override
    public String toString() {
     
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

xml 配置文件


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="student" class="com.atguigu.pojo.Student">
        <property name="name" value="小吉">property>
    bean>

    <bean id="teacher" class="com.atguigu.pojo.Teacher" autowire="byType">

    bean>
beans>

测试类

public class Test2 {
     

    public static void main(String[] args) {
     
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-spring.xml");
        Teacher teacher = (Teacher) applicationContext.getBean("teacher");
        teacher.toString();
    }
}

populateBean() 源码概览

AbstractAutowireCapableBeanFactorypopulateBean() 方法

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
     
	if (bw == null) {
     
		if (!pvs.isEmpty()) {
     
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		else {
     
			// 空对象直接返回
			return;
		}
	}

	// 给InstantiationAwareBeanPostProcessors最后一次机会在属性注入前修改Bean的属性值
	// 具体通过调用postProcessAfterInstantiation方法,如果调用返回false,表示不必继续进行依赖注入,直接返回
	boolean continueWithPropertyPopulation = true;

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

	// pvs 是一个 MutablePropertyValues 实例,里面实现了PropertyValues接口,提供属性的读写操作实现,同时可以通过调用构造函数实现深拷贝
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    // 根据bean的依赖注入方式:即是否标注有 @Autowired 注解或 autowire=“byType/byName” 的标签
    // 会遍历bean中的属性,根据类型或名称来完成相应的注入
	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
     
		// 深拷贝当前已有的配置
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// 根据名称进行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
     
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// // 根据类型进行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
     
			autowireByType(beanName, mbd, bw, newPvs);
		}
        // 结合注入后的配置,覆盖当前配置
		pvs = newPvs;
	}
    
    // 容器是否注册了InstantiationAwareBeanPostProcessor
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// 是否进行依赖检查
	boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
	if (hasInstAwareBpps || needsDepCheck) {
     
	    // 过滤出所有需要进行依赖检查的属性编辑器
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		if (hasInstAwareBpps) {
     
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
     
			    // 如果有相关的后置处理器,进行后置处理
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
     
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
     
						return;
					}
				}
			}
		}
		if (needsDepCheck) {
     
		    // 检查是否满足相关依赖关系,对应的depends-on属性,需要确保所有依赖的Bean先完成初始化
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}
	}
    // 将pvs上所有的属性填充到BeanWrapper对应的Bean实例中
	applyPropertyValues(beanName, mbd, bw, pvs);
}
  • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法,可以决定程序是否继续进行属性填充。只要有一个 InstantiationAwareBeanPostProcessor 返回 false,都会终止属性填充的过程
  • 如果标注有 @Autowired 注解或 autowire=“byType/byName” 标签,则根据 BY_NAMEBY_TYPE,提取相应依赖的 bean,并统一存入到 propertyValues
  • 应用 InstantiationAwareBeanPostProcessor.postProcessProperties()InstantiationAwareBeanPostProcessor.postProcessPropertyValues() 方法,对属性获取完毕填充前对属性的再次处理
  • 将所有 propertyValues 中的属性填充至 BeanWrapper

populateBean() 源码详解

自动装配

    // 根据bean的依赖注入方式:即是否标注有 @Autowired 注解或 autowire=“byType/byName” 的标签
    // 会遍历bean中的属性,根据类型或名称来完成相应的注入
	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
     
		// 深拷贝当前已有的配置
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// 根据名称进行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
     
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// // 根据类型进行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
     
			autowireByType(beanName, mbd, bw, newPvs);
		}
        // 结合注入后的配置,覆盖当前配置
		pvs = newPvs;
	}

如果 bean 在声明的时候指定了自动注入类型是 byNamebyType,则会根据这个规则,对 bean 内部排除某些特定的属性,进行 byNamebyType 的自动装配

自动装配之 autowireByName()

protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
     
	// 根据bw的PropertyDescriptors,遍历出所有可写的(即set方法存在),存在于BeanDefinition里的PropertyValues,且不是简单属性的属性名
    // 简单属性的判定参照下面方法,主要涵盖基本类型及其包装类,Number,Date等
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
     
		// 检查缓存bean 中是否有当前bean
		if (containsBean(propertyName)) {
     
			// 递归初始化 bean,会调用 doGetBean() 来获取bean
			Object bean = getBean(propertyName);
			pvs.add(propertyName, bean);
			// 注册依赖,将依赖关系保存到 Map> dependentBeanMapdependentBeanMap 中,key是 bean,value是 转化后的 propertyName
			registerDependentBean(propertyName, beanName);
			if (logger.isDebugEnabled()) {
     
				logger.debug("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");
			}
		}
	}
}

byName 的处理逻辑很简单:获取需要注入的 bean,然后递归调用 getBean 获取 bean 进行注入

自动装配之 autowireByType()

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);
			// 这里不解析Object的官方注释 :不要尝试按类型为Object类型自动装配:即使从技术上讲是不满意的,非简单的属性,也从没有意义。
			if (Object.class != pd.getPropertyType()) {
     
				// 获取指定属性的 set 方法
				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
				boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
				// 解析指定beanName 的属性所匹配的值,并把解析到的属性名存储在 autowiredBeanNames  中
				// 当属性存在多个封装bean时,如 @Autowired List beans,会找到所有的匹配Bean 类型的bean并将其注入。
				// 这里的返回值是真正的需要注入的属性, autowiredBeanNames 是需要注入的属性(可能是集合)的names
				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
				if (autowiredArgument != null) {
     
					// 添加到待注入的bean列表中
					pvs.add(propertyName, autowiredArgument);
				}
				// 注册依赖
				for (String autowiredBeanName : autowiredBeanNames) {
     
					// 注册依赖关系。操作 dependentBeanMap 和  dependenciesForBeanMap 集合
					registerDependentBean(autowiredBeanName, beanName);
					if (logger.isDebugEnabled()) {
     
						logger.debug("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);
		}
	}
}
  • 获取类型转换器,如果没有,默认为 bw
  • 获取(过滤)需要注入的属性
  • 对所有属性进行遍历,开始注入, 首先排除 Object.class 类型,调用resolveDependency() 方法进行校验获取对应的最后的值
  • 放入 pvs 里面,并调用 registerDependentBean() 方法注册对应的依赖和被依赖关系

使用测试代码进行调试,发现 autowiredBeanNames 的数据为下图所示

spring源码之bean的属性填充populateBean方法解读_第1张图片

applyPropertyValues() 方法

上面只是将属性保存了起来,并未真正设置到 bean 中,这里设置到 bean

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
     
	// 如果属性列表为null,直接返回
	if (pvs.isEmpty()) {
     
		return;
	}

	if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
     
		((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
	}

	MutablePropertyValues mpvs = null;
	List<PropertyValue> original;
	
	// 如果pvs 是 MutablePropertyValues 类型的封装
	if (pvs instanceof MutablePropertyValues) {
     
		mpvs = (MutablePropertyValues) pvs;
		// 判断 mpvs 中的值类型已经转换完毕,则可以直接设置到BeanWrapper 中
		if (mpvs.isConverted()) {
     
			try {
     
				bw.setPropertyValues(mpvs);
				return;
			}
			catch (BeansException ex) {
     
				throw new BeanCreationException(
							mbd.getResourceDescription(), beanName, "Error setting property values", ex);
			}
		}
		original = mpvs.getPropertyValueList();
	}
	else {
     
		original = Arrays.asList(pvs.getPropertyValues());
	}

	// 获取自定义转换类型,如果为null ,使用默认的bw, BeanWrapper 类继承了 TypeConverter 
	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
     
		converter = bw;
	}
	BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

	// 这里是创建一个深度拷贝的list,解决值引用相关的问题
	List<PropertyValue> deepCopy = new ArrayList<>(original.size());
	boolean resolveNecessary = false;
	for (PropertyValue pv : original) {
     
		// 如果已经转换之后直接保存
		if (pv.isConverted()) {
     
			deepCopy.add(pv);
		}
		else {
     
			// 进行类型转换
			String propertyName = pv.getName();
			Object originalValue = pv.getValue();
			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
			Object convertedValue = resolvedValue;
			// 检查给定的属性是否可写, 或者检查属性是否是索引或嵌套的属性,比如a.b , 或者 [a,b]
			boolean convertible = bw.isWritableProperty(propertyName) &&
					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
			// 进行类型转换
			if (convertible) {
     
				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
			}
			// 将转换转换的值保存在pv 里面,同时加到深度拷贝list里面
			if (resolvedValue == originalValue) {
     
				if (convertible) {
     
					pv.setConvertedValue(convertedValue);
				}
				deepCopy.add(pv);
			}
			else if (convertible && originalValue instanceof TypedStringValue &&
					!((TypedStringValue) originalValue).isDynamic() &&
					!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
     
				pv.setConvertedValue(convertedValue);
				deepCopy.add(pv);
			}
			else {
     
				resolveNecessary = true;
				deepCopy.add(new PropertyValue(pv, convertedValue));
			}
		}
	}
	// 设置为已经转换过,避免后续的转换
	if (mpvs != null && !resolveNecessary) {
     
		mpvs.setConverted();
	}

	// 这里就是最后将转换后的值,进行赋值填充
	try {
     
		bw.setPropertyValues(new MutablePropertyValues(deepCopy));
	}
	catch (BeansException ex) {
     
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
	}
}

关于自动装配方式

装配方式 解释
AUTOWIRE_DEFAULT 默认类型,和 AUTOWIRE_NO 相同。需要自己通过标签或者 ref 属性来指定需要注入的 bean 类型
AUTOWIRE_NO 和 AUTOWIRE_DEFAULT 相同
AUTOWIRE_BY_NAME 按照 bean 名称注入
AUTOWIRE_BY_TYPE 按照 bean 类型注入
AUTOWIRE_AUTODETECT 已过时

populateBean() 方法小结

  • AUTOWIRE_DEFAULTAUTOWIRE_NO:如果通过 标签或 ref 属性指定了需要注入 bean 的类型,则会在 populateBean() 方法中通过类 RootBeanDefinition 完成 xml 配置文件标签解析,并在该方法中完成属性填充注入
  • AUTOWIRE_BY_TYPEAUTOWIRE_BY_NAME :如果在 xml 配置文件中指定了装配方式或标注了注解 @Autowired,则会在 populateBean() 方法中通过类 RootBeanDefinition 完成 xml 配置文件标签或注解 @Autowired 的解析,并在该方法中完成属性填充注入

参考:https://blog.csdn.net/qq_36882793/article/details/106299180

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