In the previous article, we looked in detail at step 4 in doCreateBean() : the loop dependency handling of the singleton pattern, and then we looked at step 5 of doCreateBean(), “Property population,” which is the populateBean() method.

Let’s review the main flow of CreateBean:

  1. If it is singleton mode, get the BeanWrapper instance object from the factoryBeanInstanceCache cache and remove the cache
  2. callcreateBeanInstance()Instantiate the bean
  3. Post processing
  4. Singleton mode loop dependency processing, put level 3 cache
  5. fill
  6. Initialize the bean instance object
  7. Depend on the check
  8. Register the bean’s destruction method

In this chapter we will focus on Step 5: There are three ways to inject properties in Spring:

  • The XML configuration
  • Annotation way
  • Manual get\set method

XML, such as the default-Autowire attribute in the

node; Annotation methods include @value (), @resource, @Autowire, and @Qualifier. In this article, we will focus on attribute injection in annotation methods

PopulateBean (beanName, MBD, instanceWrapper)

//AbstractAutowireCapableBeanFactory.java

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// Verify the instance
	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.

	/ * * before set properties to InstantiationAwareBeanPostProcessors finally a chance to change the bean. * This post reference allows users to customize property injection. * a InstantiationAwareBeanPostProcessor types such as user achieve the post processor, and through the * postProcessAfterInstantiation method to the bean's member variables into the custom information. Of course, if there is no special requirement, just use the information in the configuration to inject. In addition, the Spring is not recommended implementation * InstantiationAwareBeanPostProcessor interface directly, if you want to implement this type of post processor, More advice * through inheritance InstantiationAwareBeanPostProcessorAdapter abstract class implements a custom post processor. * /
	boolean continueWithPropertyPopulation = true;

	/ / bean is not "synthetic" is not defined by the application itself hold InstantiationAwareBeanPostProcessor &&
<1>	if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {// Run through all BeanPostProcessors
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// Returns whether to continue populating the bean
				/ / postProcessAfterInstantiation: if should set properties on the bean returns true, otherwise it returns false
				// Normally, it should return true.
				/ / returns false, will prevent the Bean instance on this call any subsequent InstantiationAwareBeanPostProcessor instance.
				if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation =false;
					break; }}}}// If the post-processor issues a stop population command, subsequent operations are terminated
	if(! continueWithPropertyPopulation) {return;
	}
	// Get the Bean property value
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

	// Handle dependency injection

	// XML mode is the default-Autowire attribute in the 
      
        node in XML
      
<2>	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
		// Encapsulate PropertyValues into a MutablePropertyValues object
		// MutablePropertyValues allows simple manipulation of properties and provides constructors to support deep copy and construction of maps.
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// Add property values based on autowire by name if applicable.
		// Autowiring is autowiring based on the Bean name
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// Add property values based on autowire by type if applicable.
		// Autowiring is autowiring based on the Bean type
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}

		pvs = newPvs;
	}



	/ / is already registered InstantiationAwareBeanPostProcessors
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// Whether dependency checking is required (XML)
	booleanneedsDepCheck = (mbd.getDependencyCheck() ! = RootBeanDefinition.DEPENDENCY_CHECK_NONE);// Attribute injection (annotation mode)
	// IABP is registered && requires dependency checking
<3>	if (hasInstAwareBpps || needsDepCheck) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// Handle attribute injection (annotation mode)!! Such as @value (), @resource, @autowire
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return; }}}}// Dependency check (XML)
<4>		if(needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); }} <5>	if(pvs ! =null) {
		// Inject attributes (XML)applyPropertyValues(beanName, mbd, bw, pvs); }}Copy the code

It is mainly divided into the following steps:

  • Determines whether there is a custom property injection
  • Attribute injection (XML)
  • Property injection (annotation style)
  • Dependency Checking (XML)
  • Inject attributes (XML)

1.1. Determine whether there is custom attribute injection

At code <1> above:

        / * * before set properties to InstantiationAwareBeanPostProcessors finally a chance to change the bean. * This post reference allows users to customize property injection. * a InstantiationAwareBeanPostProcessor types such as user achieve the post processor, and through the * postProcessAfterInstantiation method to the bean's member variables into the custom information. Of course, if there is no special requirement, just use the information in the configuration to inject. In addition, the Spring is not recommended implementation * InstantiationAwareBeanPostProcessor interface directly, if you want to implement this type of post processor, More advice * through inheritance InstantiationAwareBeanPostProcessorAdapter abstract class implements a custom post processor. * /
	 boolean continueWithPropertyPopulation = true;

        / / bean is not "synthetic" is not defined by the application itself hold InstantiationAwareBeanPostProcessor &&
	if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {// Run through all BeanPostProcessors
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// Returns whether to continue populating the bean
				/ / postProcessAfterInstantiation: if should set properties on the bean returns true, otherwise it returns false
				// Normally, it should return true.
				/ / returns false, will prevent the Bean instance on this call any subsequent InstantiationAwareBeanPostProcessor instance.
				if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation =false;
					break; }}}}// If the post-processor issues a stop population command, subsequent operations are terminated
	if(! continueWithPropertyPopulation) {return;
	}
Copy the code

This part of the logic is clearly written in the comments.

1.2. Attribute Injection (XML)

// XML mode is the default-Autowire attribute in the 
      
        node in XML
      
	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
		// Encapsulate PropertyValues into a MutablePropertyValues object
		// MutablePropertyValues allows simple manipulation of properties and provides constructors to support deep copy and construction of maps.
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// Add property values based on autowire by name if applicable.
		// Autowiring is autowiring based on the Bean name
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// Add property values based on autowire by type if applicable.
		// Autowiring is autowiring based on the Bean type
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}

		pvs = newPvs;
	}
Copy the code

This part of the code deals with injection of XML-like attributes, such as the default-Autowire attribute in XML

nodes, because this Spring series focuses on annotations and won’t go into detail here. Emotional interest of friends can understand their own interest ~

1.2. Attribute Injection (annotation)


PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
	if (hasInstAwareBpps) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			// Handle dependency injection (annotations) such as @value (), @resource, @autowire
			pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
			if (pvs == null) {
				return; }}}}Copy the code

This code is at the heart of our analysis. First is whether the judge has registered InstantiationAwareBeanPostProcessor (rear instantiation of the Bean processors), if registered, iterate through all the post processor. We first to get to know the InstantiationAwareBeanPostProcessor class diagram of the structure:

InstantiationAwareBeanPostProcessorIs a callback handler that sets propertyValues before and after an object is instantiated. It has three methods:

        // This method is used to return an object (such as a proxy object) directly before the object is instantiated, instead of creating the object through the built-in instantiation process;
        @Nullable
	default Object postProcessBeforeInstantiation(Class
        beanClass, String beanName) throws BeansException {
		return null;
	}
	
	If false is returned before populateBean is executed after the object is instantiated, Spring will no longer automatically inject the corresponding bean instance.
	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		return true;
	}
	
	 // This callback is performed before spring processes the default member properties and applies them to the specified bean. It can be used to check and modify the properties, and the PropertyValues returned will be applied to the bean
        // @autoWired, @Resource, @Value, etc.
	@Nullable
	default PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		return pvs;
	}
Copy the code

We basically see the third method postProcessPropertyValues (), this method is through the annotation attributes into concrete realization. There are three main implementations of this method, each with different annotations.

  • AutowiredAnnotationBeanPostProcessor can handle @ Autowire, @ the Value
  • CommonAnnotationBeanPostProcessor can handle @ the Resource
  • RequiredAnnotationBeanPostProcessor can handle @ Required

1.2.1, AutowiredAnnotationBeanPostProcessor

It is the Spring container that specializes in Bean afterprocessors configured with auto-dependency injection assembly annotations (@Autowire, @Value, and other JSR-330 annotations). See Spring annotation @autowired source code analysis for details

1.2.2, CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor is commonly used in used in processing JavaEE5 Spring annotations (mainly the EJB related annotation) associated with Java6 on JAX – WS annotations, Handles annotations for @postConstruct, @PreDestroy, and other Bean lifecycle related events. The core of this post-processing is handling @Resource annotations, as well as JAX-WS related annotations. See the Spring annotation @Resource source code analysis for details

conclusionCopy the code

At this point, all attributes of the annotation mode have been injected.