Spring's bean loading process

The Spring IOC container is like a machine on an assembly line that produces products, and the beans created by Spring are like exquisite products produced at the end of the assembly line. Since it is a machine, it must be started first, and Spring is no exception. Therefore, the Bean loading process can be divided into two stages in general:

  • Container startup phase
  • Bean creation phase

1. Container startup phase:

A lot of warm-up work has been done during the startup phase of the container, which is fully prepared for the subsequent instantiation of Bean. Let’s first look at what warm-up work has been done during the startup phase of the container.

1. Configuration meta information:

The Spring IOC container separates the creation of object instances from the use of object instances. When the business needs to rely on an object, we no longer rely on us to create it manually. Just ask Spring, and Spring will give us what we need by injection. Dependent object. Now that the task of object creation is handed over to Spring, Spring needs to know some necessary information needed to create an object. And these necessary information can be the most complete xml configuration file that Spring supports in the past, or other forms of disk files such as properties, it can also be mainstream annotations, or even direct code hard-coding. In short, the necessary information required to create an object is called configuration meta-information.

<bean id="role" class="com.wbg.springxmlbean.entity.Role">
    <!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
    相当于:
    Role role=new Role();
    role.setId(1);
    role.setRoleName("高级工程师");
    role.setNote("重要人员");-->
    <property name="id" value="1"/>
    <property name="roleName" value="高级工程师"/>
    <property name="note" value="重要人员"/>
</bean>

2、BeanDefination:

In the Java world, everything is an object. The annotations scattered around the program code and the configuration meta information such as xml or other files saved on the disk must always be represented in the form of an object in the memory, just like us. The person corresponding to the Java world is a Person class, and Spring chooses to represent these configuration meta-information in memory is BeanDefination, here we will not analyze the code of BeanDefination, here we only need to know that the configuration meta-information is loaded into memory Then it can exist in the form of BeanDefination.

3、BeanDefinationReader:

How does Spring understand these configuration meta-information? This depends on our BeanDefinationReader. Different BeanDefinationReader have different functions, if we want to read xml configuration meta information, then we can use XmlBeanDefinationReader. If we want to read the properties configuration file, we can use PropertiesBeanDefinitionReader to load it. And if we want to read the annotation configuration meta information, we can use AnnotatedBeanDefinitionReader to load. We can also easily customize the BeanDefinationReader to control the loading of configuration meta-information. In general, the role of BeanDefinationReader is to load configuration meta-information and convert it into a memory form of BeanDefination , which exists in a certain place. As for where this place is, don’t worry, then look down!

4、BeanDefinationRegistry:

At this point in execution, Spring has loaded the configuration meta information that exists everywhere into the memory and converted it into the form of BeanDefination, so that when we need to create an object instance, we can find the corresponding BeanDefination and create the object. So when we need an object, where do we find the corresponding BeanDefination? How is the corresponding relationship or mapping relationship of the BeanDefination of the object found through the Bean defined id to be saved? This leads to the BeanDefinationRegistry.

After Spring by BeanDefinationReader configuration information is loaded into memory element generated corresponding BeanDefination, which will be registered to the BeanDefinationRegistry, BeanDefinationRegistry is a large storage basket BeanDefination, it also is a key-value pairs, as defined by a specific Bean id, mapped to the corresponding BeanDefination.

5、BeanFactoryPostProcessor:

BeanFactoryPostProcessor is an extension point provided by Spring in the container startup phase, which is mainly responsible for modifying and replacing each BeanDefination registered in the BeanDefinationRegistry to a certain extent. For example, some configuration information that may be modified in our configuration meta information is scattered everywhere, which is not flexible enough, and it is troublesome to modify the corresponding configuration. At this time, we can use placeholders to configure. For example, when configuring Jdbc's DataSource connection, you can configure it like this:

<bean id="dataSource"  
    class="org.apache.commons.dbcp.BasicDataSource"  
    destroy-method="close">  
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
    <property name="maxActive" value="${jdbc.maxActive}"></property>  
    <property name="maxWait" value="${jdbc.maxWait}"></property>  
    <property name="minIdle" value="${jdbc.minIdle}"></property>  
  
    <property name="driverClassName"  
        value="${jdbc.driverClassName}">  
    </property>  
    <property name="url" value="${jdbc.url}"></property>  
  
    <property name="username" value="${jdbc.username}"></property>  
    <property name="password" value="${jdbc.password}"></property>  
</bean> 

The BeanFactoryPostProcessor will make the final modification to the BeanDefination registered in the BeanDefinationRegistry, replacing the $ placeholder with the real data in the configuration file.

At this point, even if the entire container startup phase is completed, the final product of the container startup phase is the BeanDefination registered in the BeanDefinationRegistry. This is the preheating work done by Spring for Bean instantiation. Let us review what happened during the container startup phase in the form of a picture.

 

 

2. Bean acquisition phase:

In the container startup phase, the registration of the bean has been completed. If the object is configured to be lazily loaded, it will exist in the form of BeanDefination in BeanDefinationRegistry until we rely on the object instance to Spring, that is, Spring only exists when we rely on the object for the first time. Only then start the instantiation phase of the corresponding object. And if we do not choose lazy loading, after the container startup phase is completed, there is a step finishBeanFactoryInitialization(), which will immediately start the Bean instantiation phase, and instantiate everything by implicitly calling the getBean method of all dependent objects The configured Bean completes the loading of the class.

1. doGetBean(): get bean:

The overall function of doGetBean() is to check whether the bean exists in the cache or beanFactory before creating the bean object. If it exists, it will return. If it does not exist, the corresponding creation process will be carried out. Let's find the entrance of the doGetBean() method first, and read the source code of this method:

First call ApplicationContext.getBean("beanName") to get the Bean object:

applicationContext.getBean("name");

Then call AbstractApplicationContext.getBean("beanName"):

    public Object getBean(String name) throws BeansException {
        assertBeanFactoryActive(); 
        // 调用getBean 进入AbstractBeanFactory    
        return getBeanFactory().getBean(name);
    }

Then call the doGetBean() method of the AbstractBeanFactory class:

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

        /*
        1、转换beanName(别名转换):传入的参数name可能只是别名,也可能是FactoryBean,所以需要进行解析转换:
        (1)消除修饰符,比如工厂引用前缀 String FACTORY_BEAN_PREFIX = "&";
        (2)解决spring中alias标签的别名问题
        */ 
		final String beanName = transformedBeanName(name);
		Object bean;

        //2、尝试从缓存中去加载实例,如果获取到了就直接返回
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		//如果缓存中存在对应的bean
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			
			//3、缓存渠道的bean的实例化。从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化。
			// 此时会进行 合并RootBeanDefinition、BeanPostProcessor进行实例前置处理、实例化、实例后置处理。
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
        // 如果缓存中没有对应bean
		else { 
		    //4、循环依赖检查。 (构造器的循环依赖)循环依赖存在,则报错。
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

            // 5、如果缓存中没有数据,就会转到父类工厂去加载
            //获取父工厂
			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			
            //!containsBeanDefinition(beanName)就是检测如果当前加载的xml配置文件中不包含beanName所对应的配置,就只能到parentBeanFacotory去尝试加载bean。
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

            //6、存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。
			try {
                // XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但Bean的后续处理是针对于RootBeanDefinition的,所以需要转换后才能进行后续操作。
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				//7、初始化依赖的bean
				String[] dependsOn = mbd.getDependsOn();
				//bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
						}
						registerDependentBean(dependsOnBean, beanName);
						getBean(dependsOnBean);
					}
				}

                //8、创建bean
				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								// Explicitly remove instance from singleton cache: It might have been put there
								// eagerly by the creation process, to allow for circular reference resolution.
								// Also remove any beans that received a temporary reference to the bean.
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								beforePrototypeCreation(beanName);
								try {
									return createBean(beanName, mbd, args);
								}
								finally {
									afterPrototypeCreation(beanName);
								}
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

2. Get the singleton bean from the cache: getSingleton(String beanName, boolean allowEarlyReference)

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// 从缓存池中获取bean:singletonObjects 一级缓
    Object singletonObject = this.singletonObjects.get(beanName);
	
    // 如果一级缓存中为null,再判断是否正在创建
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		// 加锁,防止并发创建
		synchronized (this.singletonObjects) {
			// 从二级缓存中获取bean,如果此 bean 正在加载则不处理
			singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
				// 当某些方法需要提前初始化,调用 addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

In Spring, beans are singletons by default, and the singleton of the same container will only be created once. When the bean is subsequently obtained, it is directly obtained from the singleton cache singletonObjects. And because the singleton cache is a public variable, when it is operated, a lock operation is performed, which avoids the overwriting operation of concurrent modification or reading by multiple threads.

There is also an earlySingletonObjects variable, which is also a singleton cache, and is also used to store the relationship between beanName and bean instance creation. Unlike singletonFactories, when a singleton bean is put into the early singleton cache, it must be removed from singletonFactories. The two are mutually exclusive and are mainly used to solve the problem of circular dependencies.

3. Get the object from the Bean instance: getObjectForBeanInstance()

In the getBean() method, getObjectForBeanInstance() is a high-frequency method. This method appears whether to obtain the bean in the singleton cache or to load the bean according to different scope strategies. Because the bean obtained from the cache is the bean in the original state, the bean needs to be instantiated here.

get_object_from_factory_bean

Summary of method flow:

  • (1) Verify the bean type: determine whether it is a factory bean
  • (2) No processing for non-FactoryBean
  • (3) Processing FactoryBean: If it is a FactoryBean type, first convert the bean, and then delegate to the getObjectFromFactoryBean() method for processing.

In this method, there is a special treatment for the factory bean, and the type returned by the FactoryBean.getObject() method is finally obtained.

4, 获 康 Example: getSingleton (String beanName, ObjectFactory <?> SingletonFactory)

// Create bean instance. 创建 bean 实例
// singleton 单例模式(最常使用)
if (mbd.isSingleton()) {
    // 第二个参数的回调接口,接口是 org.springframework.beans.factory.ObjectFactory#getObject
    // 接口实现的方法是 createBean(beanName, mbd, args)
	sharedInstance = getSingleton(beanName, () -> {
		return createBean(beanName, mbd, args);
		// 省略了 try / catch
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

Let's see what the getSingleton() method does:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	// 注释 4.7 全局变量,加锁
	synchronized (this.singletonObjects) {
		//1、再次检查是否已经被加载了,单例模式就是可以复用已经创建的 bean
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			//2、初始化前操作,校验是否 beanName 是否有别的线程在初始化,并记录beanName的初始化状态
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			//3、调用createBean方法实例化bean
			singletonObject = singletonFactory.getObject();
			newSingleton = true;
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = null;
			}
			//4、初始化后的操作,移除初始化状态
			afterSingletonCreation(beanName);
			if (newSingleton) {
				//5、加入缓存
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}

The process of this step is:

  • (1) Check again whether the cache has been loaded
  • (2) If it is not loaded, record the loading status of beanName
  • (3) Call the createBean() method to instantiate the bean
  • (4) After the bean instantiation is complete, remove the initialization state
  • (5) Record the instantiation result to the cache and delete the various auxiliary states recorded during the bean loading process

For steps (2) and (4), it is used to record the loading status of the bean, which is used to detect circular dependencies. The key method lies in the third step, calling the getObject() method of ObjectFactory. The actual callback interface implements the createBean() method to create the object.

 

Three, the instantiation stage of Bean:

(1) Preparation before creating bean:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	RootBeanDefinition mbdToUse = mbd;
	// 确保此时bean类已经被解析,并且克隆 bean 定义,以防动态解析的类不能存储在共享合并 bean 定义中。
	//1、锁定 class,根据设置的 class 属性或者根据 className 来解析 Class
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}
	// Prepare method overrides.
	//2、验证及准备覆盖的方法
    mbdToUse.prepareMethodOverrides();
    //3、解析指定bean,让 beanPostProcessor 有机会返回代理而不是目标bean实例。
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
    	// 短路操作,如果代理成功创建 bean 后,直接返回
    	return bean;
    }
	
	//4、创建 bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	return beanInstance;
}

Let's summarize this process first:

  • (1) Resolve Class according to the set class attribute or according to className
  • (2) The method of verification and preparation for coverage This method is used to process the following two configurations: when we parse the default label, we will recognize the lookup-method and replaced-method attributes, and then the loading of these two configurations will be stored in a unified manner In the methodOverrides attribute in beanDefinition.
  • (3) Apply the post-processor before initialization to analyze whether the specified bean has a short-circuit operation before initialization
  • (4) Create a bean

1. Deal with the Override attribute:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// Check that lookup methods exists.
	if (hasMethodOverrides()) {
		Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
		synchronized (overrides) {
			for (MethodOverride mo : overrides) {
				// 处理 override 属性
				prepareMethodOverride(mo);
			}
		}
	}
}

As you can see, get the list of overloaded methods of the class, then traverse, and process them one by one. The specific processing is the lookup-method and replaced-method attributes. The configuration parsed in this step will be stored in the methodOverrides attribute in beanDefinition in preparation for the instantiation later. If the methodOverrides attribute is detected when the bean is instantiated, the current bean will be dynamically generated to generate a proxy, and the corresponding interceptor will be used to enhance the bean.

2. Pre-processing before instantiation:

// 让 beanPostProcessor 有机会返回代理而不是目标bean实例。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
	// 短路操作,如果代理成功创建 bean 后,直接返回
	return bean;
}

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
			    // 执行前置拦截器的操作
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
				    // 执行后置拦截器的操作
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
}

Before the doCreateBean() method, there is a short-circuit operation. If the post-processor succeeds, the proxy bean will be returned.

In the resolveBeforeInstantiation() method, two key methods are executed to ensure that the bean information has been parsed. From the comments, one is the operation of the pre-interceptor and the other is the operation of the post-interceptor.

If the first pre-interceptor is instantiated successfully, the singleton bean has been put into the cache. It will no longer go through the creation process of ordinary beans, and there is no chance to make post-processor calls, so here is the second one The step is for this bean to also apply the postProcessAfterInitialization method of the post processor. And if the bean has no specific pre-processing, it means that the bean is an ordinary bean, then follow the steps below to create

(Two) bean creation: doCreateBean()

At this step, the bean object is actually created. The corresponding source code is in the doCreateBean() method. Here, let’s take a look at the overall creation process of the bean, and then do the important methods. analysis:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
    //1、如果bean是单例,就先清除缓存中的bean信息
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		//2、根据指定bean使用对应的策略实例化bean,例如:工厂方法,构造函数自动注入,简单初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
	//3、允许后处理处理器修改合并后的bean定义
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			mbd.postProcessed = true;
		}
	}
	//4、是否需要提前曝光,用来解决循环依赖时使用
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		// 第二个参数是回调接口,实现的功能是将切面动态织入 bean
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
	Object exposedObject = bean;
    //5、对 bean 进行填充,将各个属性值注入
    // 如果存在对其它 bean 的依赖,将会递归初始化依赖的 bean
    populateBean(beanName, mbd, instanceWrapper);
    //6、调用初始化方法,例如 init-method
    exposedObject = initializeBean(beanName, exposedObject, mbd);
	
    //7、循环依赖检查
	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		// earlySingletonReference 只有在检测到有循环依赖的情况下才 不为空
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				// 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
				exposedObject = earlySingletonReference;
			}
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					// 检查依赖
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				// bean 创建后,它所依赖的 bean 一定是已经创建了
				// 在上面已经找到它有依赖的 bean,如果 actualDependentBeans 不为空
				// 表示还有依赖的 bean 没有初始化完成,也就是存在循环依赖
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName);
			}
		}
	}
	// Register bean as disposable.
	// 8、根据 scope 注册 bean
	registerDisposableBeanIfNecessary(beanName, bean, mbd);
	return exposedObject;
}

The main flow of this doCreateBean() method can be summarized as:

  • (1) If the bean to be loaded is a singleton, first clear the bean information in the cache
  • (2) Instantiate bean, convert BeanDifinition into BeanWrapper
  • (3) The post processor modifies the merged bean definition: the processing of the merged bean, the Autowired annotation formally implements pre-analysis such as type through this method
  • (4) Dependency handling, exposing bean references in advance, mainly used to solve the problem of circular dependencies
  • (5) Attribute filling: fill all attributes into the bean instance, if there is a dependency on other beans, the dependent bean will be recursively initialized
  • (6) Initialization bean: such as afeterPropertiesSet() and init-method property configuration method
  • (7) Circular dependency check
  • (8) Register DisposableBean: This step is used to process the destroy-method attribute. Register in this step so that it can be called when the object is destroyed.
  • (9) Complete the creation and return.

1, createBeanInstance (): instantiate the bean object

In the above step (2), what is done is to instantiate the bean, and then return to the BeanWrapper.

The process of this step of createBeanInstance() mainly instantiates the bean object in two ways, one is the factory method, and the other is the constructor. The configuration in the RootBeanDefinition passed in is selected to generate a bean instance, and the function is roughly introduced:

  • If there is a factory method, use the factory method for initialization
  • If you use parameterized construction lines to instantiate the bean: a class has multiple constructors, and each constructor has different parameters, so you need to lock the constructor according to the parameters to instantiate the bean
  • If there is neither a factory method nor a constructor with parameters, the default constructor will be used to instantiate the bean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
	// Make sure bean class is actually resolved at this point.
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	// Shortcut when re-creating the same bean...
	boolean resolved = false;
	boolean autowireNecessary = false;
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
			// 如果一个类有多个构造函数,每个构造函数都有不同的参数,调用前需要进行判断对应的构造函数或者工厂方法
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true;
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	// 如果已经解析过,不需要再次解析
	if (resolved) {
		if (autowireNecessary) {
			// 实际解析的是 org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor
			// 构造函数自动注入
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
			// 使用默认的构造函数
			return instantiateBean(beanName, mbd);
		}
	}
    // Candidate constructors for autowiring? 需要根据参数解析构造函数
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		return autowireConstructor(beanName, mbd, ctors, args);
	}
	// Preferred constructors for default construction?
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
		// 构造函数注入
		return autowireConstructor(beanName, mbd, ctors, null);
	}
	// No special handling: simply use no-arg constructor. 没有特殊的处理,使用默认构造函数构造
	return instantiateBean(beanName, mbd);
}

Here, we briefly introduce what BeanWrapper is:

The Beans in Spring do not exist in their original appearance. Since the Spring IOC container has to manage multiple types of objects, in order to unify the access to different types of objects, Spring puts a layer on all the created Bean instances. jacket, this jacket is BeanWrapper, BeanWrapper actually is a simple package reflected the relevant API, making use of the upper reflector complete the relevant business logic greatly simplify, we want to get the properties of an object, an object's method call, not now You need to write complicated reflection APIs and handle a bunch of troublesome exceptions. You can complete related operations directly through BeanWrapper, which is not too cool.

2. Circular dependency:

This corresponds to the previous step (4) process, exposing bean references in advance, mainly to solve the problem of circular dependencies

// 是否需要提前曝光,用来解决循环依赖时使用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
		isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
	// 第二个参数是回调接口,实现的功能是将切面动态织入 bean
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

The key method is addSingletonFactory, which is used to add the ObjectFactory that creates the instance to the singleton factory before the bean starts to initialize. ObjectFactory is the factory used when creating objects. When the object is instantiated, it will judge whether the object it depends on has been created. The basis of the judgment is to check whether the ObjectFactory of the dependent object is in the singleton cache. If it is not created, the dependent object will be created first, and then the ObjectFactory will be placed Singleton cache.

If there is a circular dependency at this time, it needs to be exposed in advance so that the relying party can find and instantiate it normally.

You can read this article about circular dependencies: https://blog.csdn.net/a745233700/article/details/110914620

3. populateBean(): attribute injection

This corresponds to the previous step (5), filling in attributes according to different injection types, and then calling the post processor for processing, and finally applying the attributes to the bean. The main process is as follows:

(1) Call the postProcessAfterInstantiation method of the InstantiationAwareBeanPostProcessor processor to determine whether the control program continues to fill in the attributes

(2) According to the injection type (byType/byName), extract dependencies and store them in PropertyValues ​​uniformly

(3) Determine whether BeanPostProcessor and dependency check are needed:

  • If there is a post processor, the postProcessProperties method of the InstantiationAwareBeanPostProcessor processor will be used to process the properties again before the properties are obtained and filled.
  • Use the checkDependencies method to check dependencies

(4) Fill all parsed properties in PropertyValues ​​into BeanWrapper

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// 给 awareBeanPostProcessor 后处理器最后一次机会,在属性设置之前修改bean的属性
	boolean continueWithPropertyPopulation = true;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		...
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
			continueWithPropertyPopulation = false;
			break;
		}
        ...
	}
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
	int resolvedAutowireMode = mbd.getResolvedAutowireMode();
	if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		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;
    // 从 beanPostProcessors 对象中提取 BeanPostProcessor 结果集,遍历后处理器
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
    	...
    }
	// 在前面也出现过,用来进行依赖检查
    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    checkDependencies(beanName, mbd, filteredPds, pvs);
	// 将属性应用到 bean 中,使用深拷贝,将子类的属性一并拷贝
	applyPropertyValues(beanName, mbd, bw, pvs);
}

4. initializeBean(): initialize the bean

This corresponds to the previous step (6), which is mainly used to call the initialization method we set, but within the method, other operations are also done. First, let's look at the source code:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    //1、处理Aware接口
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		// 如果没有 securityManage,方法里面校验了 bean 的类型,需要引用 Aware 接口
		// 对特殊的 bean 处理:Aware/ BeanClassLoader / BeanFactoryAware
		invokeAwareMethods(beanName, bean);
	}

    //2、执行BeanPostProcessor前置处理:
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}
	//3、调用用户自定义的 init-method 方法
	invokeInitMethods(beanName, wrappedBean, mbd);

    //4、执行BeanPostProcessor后置处理
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

In this step of the process, the main processing operations are:

(1) Processing Aware interface:

Spring will detect whether the object implements the xxxAware interface. Through the Aware type interface, we can get some corresponding resources of the Spring container and inject them:

  • ① If this Bean implements the BeanNameAware interface, it will call the setBeanName(String beanId) method it implements and pass in the Bean's name;
  • ② If this Bean implements the BeanClassLoaderAware interface, call the setBeanClassLoader() method and pass in the instance of the ClassLoader object.
  • ② If this Bean implements the BeanFactoryAware interface, it will call the setBeanFactory() method it implements, passing the Spring factory itself.
  • ③If this Bean implements the ApplicationContextAware interface, it will call the setApplicationContext(ApplicationContext) method and pass in the Spring context;

(2) Execute BeanPostProcessor pre-processing:

If you want to perform some custom pre-processing before the Bean is initialized, you can make the Bean implement the BeanPostProcessor interface, which will call the postProcessBeforeInitialization(Object obj, String s) method.

(3) Call the custom init method:

This step is to find the user-defined constructor, and then call it.

① If the Bean implements the InitializingBean interface, execute the afeterPropertiesSet() method

② If the bean is configured with the init-method attribute in the Spring configuration file, it will automatically call its configured initialization method.

(4) Execute BeanPostProcessor post-processing:

If the Bean implements the BeanPostProcessor interface, the postProcessAfterInitialization(Object obj, String s) method will be called; since this method is called at the end of Bean initialization, it can be applied to memory or caching technology;

In the container startup phase, we talked about BeanFactoryPostProcessor, here we talked about BeanPostProcessor, then what is the difference between BeanFactoryPostProcessor and BeanPostProcessor?

  • BeanFactoryPostProcessor exists in the container startup stage, while BeanPostProcessor exists in the object instantiation stage. BeanFactoryPostProcessor focuses on the modification of the configuration before the object is created, while the BeanPostProcessor stage focuses on the function enhancement, replacement and other operations after the object has been created , so that it is easy to distinguish .
  • BeanPostProcessor and BeanFactoryPostProcessor are both powerful extension points of Spring in the bean production process. The famous AOP (Aspect Oriented Programming) in Spring actually relies on BeanPostProcessor to enhance the Bean object function.

5. Register disposableBean:

This step is to register the disposableBean according to different scopes. At the same time, user-defined destruction logic will be registered. There are two ways like custom initialization logic: (1) destroy() of the DisposableBean interface; (2) the method of destroy-method parameter configuration.

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
	AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
	if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        // 单例模式
		if (mbd.isSingleton()) {
			// 注册 DisposableBean
			registerDisposableBean(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
		else {
			// A bean with a custom scope...
			Scope scope = this.scopes.get(mbd.getScope());
			scope.registerDestructionCallback(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
	}
}

6. Use and destruction:

After the above steps, Spring has finally completed the creation of the Bean. When the Spring Bean is finished serving us, it will soon die (usually when the container is closed). At this time, Spring will call us in a callback mode. Customized destruction logic, and then Bean finished his glorious life like this!

7. Summary:

Finally, let's take a look at the execution order of the Bean instantiation phase through a picture:

 

Reference article:

https://juejin.cn/post/6844903871353978894#heading-5

https://juejin.cn/post/6929672218322731022#heading-0

Guess you like

Origin blog.csdn.net/a745233700/article/details/113840727