Spring source code analysis -- instantiation of Bean

Keywords: Attribute Spring

3, Bean instantiation

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();
 
			// Tell the subclass to refresh the internal bean factory.
			
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			
			prepareBeanFactory(beanFactory);
 
			try {
				// Allows post-processing of the bean factory in context subclasses.
				
				postProcessBeanFactory(beanFactory);
 
				// Invoke factory processors registered as beans in the context.
				
				invokeBeanFactoryPostProcessors(beanFactory);
 
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
 
				// Initialize message source for this context.
				initMessageSource();
 
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();
 
				// Initialize other special beans in specific context subclasses.
				onRefresh();
 
				// Check for listener beans and register them.
				registerListeners();
 
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);
 
				// Last step: publish corresponding event.
				finishRefresh();
			}
 
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
 
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();
 
				// Reset 'active' flag.
				cancelRefresh(ex);
 
				// Propagate exception to caller.
				throw ex;
			}
 
			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

6,initMessageSource

Initialize the messageSource component for internationalization, message binding and message parsing

7,initApplicationEventMulticaster()

Register event multicast object based on event development with container

8,onrefresh()

Empty method, which is left to subclass inheritance to implement personality change configuration

9,registerListeners()

Add all listener objects to the multicast object for subsequent event dispatch

10,finishBeanFactoryInitialization(beanFactory)

Instantiate all remaining (non lazy loading) singletons

getBean is called in the preInstantiateSingletons method to create the instantiated bean.

We focus on the doGetBean method. First, we find it from the single instance cache. If we don't find it, we will first determine whether it is the bean being created

Object sharedInstance = getSingleton(beanName);

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// First look from the single instance cache, if not, it will first determine whether the bean is being created
		// Issingletoncurrentlycreation determines whether the corresponding singleton object is being created
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				// Save all pre exposed singletons in earlySingletonObjects, and try to find them from earlySingletonObjects
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					// If early dependency is allowed, you can try to find the corresponding singleton factories from singleton factories
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//Create beans and cache pre exposed beans, that is, beans without attribute injection, to solve circular dependency
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

Then we will judge whether the bean = getObjectForBeanInstance(sharedInstance, name, beanName, null) is a normal bean or factorybean. If it is factorybean, we will call the getObject() method of factorybean to return the bean without instantiation.

if (!typeCheckOnly) {
// Tag bean to be created
markBeanAsCreated(beanName);
}

It needs to be noted that the bean is being created, because there will be A circular dependency problem when injecting attributes. If A has the attribute of B and B has the attribute of A, then getBean(A), Get the instance of A, but it has not been injected yet; when the injection starts, find the B attribute, start getBean(B), and get the instance of B; start to inject B, and find the A attribute, so you can get the A that has not been injected yet. That is to say, when building A single example, A that has not completed injection will be exposed in advance, so that B can complete the injection.

This is the creation of dependency classes

if (dependsOn != null) {
	for (String dep : dependsOn) {
		if (isDependent(beanName, dep)) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
		registerDependentBean(dep, beanName);
				try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

Determine whether it is a single instance. If it is a single instance, de instantiate the bean

if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		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);
	}

First understand what is BeanPostProcessor. BeanPostProcessor is an extension point of Spring container. It can carry out custom instantiation, initialization, dependency assembly, dependency check and other processes, that is, it can override the default instantiation, and it can also enhance initialization, dependency injection, dependency check and other processes.

public interface BeanPostProcessor {
    @Nullable    
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        
return bean;    
}
 @Nullable    
default Object postProcessAfterInitialization(Object bean, String beanName) throws  BeansException {        
return bean;    
} 
}

 

Nine BeanPostProcessor calls will be used to create the bean. Now we focus on the createBean method,

1. First call to postprocessor

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// Directly return the replaced object instance, and no longer instantiate the target object
return bean;
}

The post processor before instantiation calls the instantiation awarebeanpostprocessor. Through the above code, the pre-processing (custom instantiated bean, such as creating corresponding proxy object) and post-processing (such as dependency assembly of the custom instantiated bean) of instantiation can be performed. Call the postprocessbeforeinstance method of instantiaawarebeanpostprocessor

2. Second call to postprocessor

It is called in doCreateBean.

instanceWrapper = createBeanInstance(beanName, mbd, args);

Determine the candidate constructors to be used for the given bean, check all registered constructors, implement the class Autowired annotationbeanpostprocessor, scan the @ Autowired decorated constructors, and determine the constructor used to create the object (default, primary). Call the determineCandidateConstructors method of smartinstantiaawarebeanpostprocessor


3. The third call to the postprocessor

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

The post processor is allowed to modify the merged bean definition and implement the class Autowired annotation beanpostprocessor, which is used to scan the properties and methods decorated by @ Autowired and @ Value and encapsulate them into InjectionMetadata. Call the postProcessMergedBeanDefinition of the MergedBeanDefinitionPostProcessor.

4. The fourth call to the postprocessor

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

Get the bean reference exposed in advance. It is mainly used to solve the problem of circular reference. Only a singleton object can call this method. Call the getEarlyBeanReference method of smartinstantiaoawarebeanpostprocessor

5. The fifth and sixth call to the postprocessor

populateBean(beanName, mbd, instanceWrapper)

The fifth time:

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

Call the postprocessafterinstance method of instantiaawarebeanpostprocessor

After the object is instantiated, the object is instantiated, but the property of the object is not set. If the method returns fasle, the subsequent property settings are ignored. Return true, and set the property value according to the normal process.

The sixth time:

	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;
				}
			}
The property value can be modified in the method (at this time, the property value has not been set, but the property value that would have been set can be modified). If the postprocessafterinstance method returns false, the method will not be called. When @ Autowired attribute injection is used, Autowired annotation beanpostprocessor is called

6. Seventh, eight calls to the postprocessor

exposedObject = initializeBean(beanName, exposedObject, mbd)

The seventh time:

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)

In the method, the init method of the bean life cycle callback will also be executed, and the call to the InitializingBean interface will also be implemented. Because the parent class of RequestMappingHandlerMapping implements the InitializingBean interface, the registration of RequestMapping will be completed here.

If @ PostConstruct is configured, InitDestroyAnnotationBeanPostProcessor will be called

((InitializingBean) bean).afterPropertiesSet();

The eighth time:

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

This is mainly the implementation of aop. AbstractAutoProxyCreator calls postProcessAfterInitialization

7. Ninth call to postprocessor

registerDisposableBeanIfNecessary(beanName, bean, mbd)

Determine whether the given bean instance needs to destroy the postprocessor, and destroy the postprocessor of the DestructionAwareBeanPostProcessor bean

36 original articles published, 52 praised, 40000 visitors+
Private letter follow

Posted by StateGuy on Wed, 04 Mar 2020 03:31:30 -0800