This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
Spring originally configured beans through XML files, and this article starts with XML file configuration as an entry point into the bean life cycle.
Guess the bean’s life cycle
With a brief example of XML configuration, you can configure our bean as follows.
<bean id=? class=? > <property name=? value=? > <property name=? ref=? > </bean> <bean id=? class=? > <constructor-arg name=? value=? > <constructor-arg name=? ref=? > </bean>Copy the code
So how do beans in XML load into the Spring container? Here’s what we can guess:
In the following chapters, we also generally follow the guess process, reading the source code step by step to find out what the real life cycle of the bean is.
Two, a few questions
2.1 How does Spring instantiate objects?
The common ways we know how to instantiate objects are: 1) new() 2) reflection 3) Factory mode
In what way is Spring? As we all know, spring beans default scope singletons, so the new() approach is definitely not good, let’s pretend that Spring defaults to reflection and see what the source code implementation looks like.
Common reflection modes:
1) Class clazz = class.forname () 2) Class clazz = Class name. Class 3) Class clazz = object name. getClass()Copy the code
Once you have the clazz file, you can instantiate the object in the following way.
Constructor ctor = clazz.getDeclaredConstructor();
Object object = ctor.newInstance();
Copy the code
2.2 What do instantiations and initializations do? What is the state of the bean at this point?
As we learned from the JVM class loading mechanism, classes are loaded with a preparation phase and an initialization phase, and during the preparation phase, static files are allocated memory in the method area and assigned default values.
The above class loading phase is actually the same as the Spring bean instantiation and initialization phases. In the instantiation phase, a bean object is generated and a default value is assigned. At initialization, an assignment is made to the bean.
The specific operations are summarized in the following picture:
Three, follow the code to find the process
Let’s start by actually following the code to find the life cycle of a bean in Spring. In the Spring, the whole lifecycle of the bean is actually AbstractApplicationContext the refresh method.
Public void refresh () throws BeansException, an IllegalStateException {synchronized (enclosing startupShutdownMonitor) {/ /, Record the container's startup time, startupDate, mark the container as active, initialize the context such as file path information, and verify that the required properties are filled in prepareRefresh(); // Get the new beanFactory, Destruction of the original the beanFactory, generated for each bean BeanDefinition ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory (); PrepareBeanFactory (beanFactory); prepareBeanFactory(beanFactory); Try {// template method, at which point all BeanDefinitions have been loaded, but not yet instantiated. // Allow beanFactory extension processing in subclasses. For example, add ware related interface auto-assembly Settings, add post-processor, etc., is a subclass extension prepareBeanFactory(beanFactory) method postProcessBeanFactory(beanFactory); // Instantiate and call all registered beanFactory postprocessors. After the beanFactory standard initialization) invokeBeanFactoryPostProcessors (the beanFactory); / / registered beans rear processor registerBeanPostProcessors (the beanFactory); // Initialize context message initMessageSource(); / / initialize event initApplicationEventMulticaster (); // The template method allows you to customize the logic when the container is refreshed. Different Spring containers do different things. onRefresh(); // Listeners can register early Application events registerListeners(); / / instantiate all the rest of the (not lazy loading) singleton / / such as invokeBeanFactoryPostProcessors method according to various annotations parsing out of class, at this time will be initialized. // The instantiation process of various BeanpostProcessors comes into play. finishBeanFactoryInitialization(beanFactory); // Other things you need to do after refresh is done. // Clear the context resource cache (such as ASM metadata in the scan) // initialize the context Lifecycle handler and refresh (find the bean in the Spring container that implements the Lifecycle interface and execute the start() method). // Publish the ContextRefreshedEvent event to inform the corresponding ApplicationListener of the response operation finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy the generated bean destroyBeans(); 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(); }}}Copy the code
1. Load the configuration file
We know that Spring defines beans as XML or annotations, so how do you load defined configuration files into the IOC container? Spring provides an interface specification BeanDefinitionReader:
In addition, the interface defines AnnotatedBeanDefinitionReader for annotations.
With these two components, our overall flow will look like the following:
The configuration file is loaded into spring’s IOC container through the above interfaces and classes, and processed into a bean structure that meets the requirements of the IOC container.
Here is a concrete look at the source code is how to achieve:
Public void refresh () throws BeansException, an IllegalStateException {synchronized (enclosing startupShutdownMonitor) {/ /, Record the container's startup time, startupDate, mark the container as active, initialize the context such as file path information, and verify that the required properties are filled in prepareRefresh(); // Get the new beanFactory, Destruction of the original the beanFactory, generated for each bean BeanDefinition ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory ();Copy the code
In the Refresh method, the current focus is on the obtainFreshBeanFactory() method.
Protected ConfigurableListableBeanFactory obtainFreshBeanFactory () {/ / refresh refreshBeanFactory (); return getBeanFactory(); }Copy the code
Continue tracing refreshBeanFactory().
Protected final void refreshBeanFactory() throws BeansException {// Destroy original beanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } the try {/ / create a the BeanFactory DefaultListableBeanFactory the BeanFactory = createBeanFactory (); / / to the current bean set id the beanFactory setSerializationId (getId ()); CustomizeBeanFactory (beanFactory); customizeBeanFactory(beanFactory); // Load bean information from configuration file as beanDefinition loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); }}Copy the code
Focus on loadBeanDefinitions(beanFactory).
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create an XML bean definition reader for beanFactory XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); / / to beanDefinitionReader set the environment variable beanDefinitionReader. SetEnvironment (getEnvironment ()); / / to beanDefinitionReader set resource loader beanDefinitionReader. SetResourceLoader (this); / / to beanDefinitionReader set solid parser beanDefinitionReader. SetEntityResolver (new ResourceEntityResolver (this)); // No real content initBeanDefinitionReader(beanDefinitionReader); // Get bean definitions loadBeanDefinitions(beanDefinitionReader) from configuration files; }Copy the code
Enter loadBeanDefinitions (beanDefinitionReader).
Protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {// Obtain the configuration file address, / web-INF/XML file String[] configLocations = getConfigLocations(); if (configLocations ! = null) {/ / traverse the for (String configLocation: configLocations) {/ / load the bean definition reader. LoadBeanDefinitions (configLocation); }}}Copy the code
I won’t go into details here, but I will recursively parse each node of the XML file step by step.
After your analysis above, we found that with BeanDefinitionReader parsing, the bean information in XML eventually became a BeanDefinition that can be accepted by the IOC container, and a BeanFactory was created. The lifecycle of the bean with its own weight should look like the following figure:
2. Do your homework
In the previous section, BeanDefinition and Beanfactory were generated by loading the configuration file, and you continue to trace the Refresh code. During the execution of the code, there is a lot of preparatory work to be done, such as providing BeanFactoryPostProcessor, registering BeanFactoryPostProcessor, internationalization, initializing event multicast, registering listeners, etc
Public void refresh () throws BeansException, an IllegalStateException {synchronized (enclosing startupShutdownMonitor) {/ /, Record the container's startup time, startupDate, mark the container as active, initialize the context such as file path information, and verify that the required properties are filled in prepareRefresh(); // Get the new beanFactory, Destruction of the original the beanFactory, generated for each bean BeanDefinition ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory (); PrepareBeanFactory (beanFactory); prepareBeanFactory(beanFactory); Try {// Empty template method, at which point all BeanDefinitions have been loaded, but have not yet been instantiated. // Allow beanFactory extension processing in subclasses. For example, add ware related interface auto-assembly Settings, add post-processor, etc., is a subclass extension prepareBeanFactory(beanFactory) method postProcessBeanFactory(beanFactory); // Instantiate and call all registered beanFactory postprocessors. After the beanFactory standard initialization) invokeBeanFactoryPostProcessors (the beanFactory); / / registered beans rear processor registerBeanPostProcessors (the beanFactory); // Initialize context message initMessageSource(); / / initialize event initApplicationEventMulticaster (); // The template method allows you to customize the logic when the container is refreshed. Different Spring containers do different things. onRefresh(); // Listeners can register early Application events registerListeners();Copy the code
This process is basically preparatory work, except that BeanFactoryPostProcesser can enhance beans already defined. After you’ve gone through these stages, the process is as follows.
3. Instantiation
Now that the preparation is complete, we can actually instantiate the bean:
/ / instantiate all the remaining (not lazy loading) singleton finishBeanFactoryInitialization (the beanFactory);Copy the code
Set the following attributes:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (! beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); / / instantiate all the remaining singleton bean. The beanFactory preInstantiateSingletons (); }Copy the code
Tracking the beanFactory. PreInstantiateSingletons () method, ignore other method, directly to the getBean ().
public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } List<String> beanNames = new ArrayList<>(this.beandefinitionNames); / / iterates through all not delay bean instantiation for (String beanName: beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition (beanName); if (! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean<? > factory = (FactoryBean<? >) bean; boolean isEagerInit; if (System.getSecurityManager() ! = null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<? >) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); }}} else {// getBean getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() ! = null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); }}}}Copy the code
Here’s how to actually instantiate the bean:
@override public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false); }Copy the code
When first started, the bean has not been created, we trace directly to createBean(beanName, MBD, args) :
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance ! = null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory ! = null && ! containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args ! = null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType ! = null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (! typeCheckOnly) { markBeanAsCreated(beanName); } try { RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); 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); 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); } 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(); if (! Stringutils.haslength (scopeName)) {throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'"); } 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, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); }}); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new ScopeNotActiveException(beanName, scopeName, ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. if (requiredType ! = null && ! requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }Copy the code
CreateBean (beanName, MBD, args);
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<? > resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass ! = null && ! mbd.hasBeanClass() && mbd.getBeanClassName() ! = null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean ! = null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); }}Copy the code
Continue tracing the doCreateBean(beanName, mbdToUse, args) of the above method, which is getting closer to reflection creating instantiated objects:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) {// createBeanInstance instanceWrapper = createBeanInstance(beanName, MBD, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass(); if (beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (! mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; Try {// Fill the property populateBean(beanName, MBD, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference ! = null) { if (exposedObject == bean) { 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); } } if (! actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }Copy the code
Trace createBeanInstance(beanName, MBD, args) :
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class<? > beanClass = resolveBeanClass(mbd, beanName); if (beanClass ! = null && ! Modifier.isPublic(beanClass.getModifiers()) && ! mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } Supplier<? > instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier ! = null) { return obtainFromSupplier(instanceSupplier, beanName); } if (mbd.getFactoryMethodName() ! = null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 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) { 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); } return instantiateBean(beanName, MBD); }Copy the code
Trace instantiateBean(beanName, MBD) :
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance; if (System.getSecurityManager() ! = null) { beanInstance = AccessController.doPrivileged( (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext()); } else {beanInstance = getInstantiationStrategy().instantiate(MBD, beanName, this); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); }}Copy the code
Tracking getInstantiationStrategy (). Instantiate (MBD, beanName, this), we found the familiar a code clazz. GetDeclaredConstructor (), just to prove that the problem in front of, Spring is through reflection implementation bean instantiation, and by the last line of code BeanUtils. InstantiateClass (constructorToUse), in this method performed inside the bean instantiation:
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (! bd.hasMethodOverrides()) { Constructor<? > constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<? >) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<? > clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() ! = null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<? >>) clazz::getDeclaredConstructor); } else {/ / reflection to obtain the structure of the bean constructorToUse = clazz. GetDeclaredConstructor (); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); }}Copy the code
Through the long code trace above, we can see that the bean is instantiated through the BeanFactory through a series of processing, and finally invokes the initialization policy, using reflection mode instantiation, then the final life cycle will be like the following:
4. Initialize
After the bean is instantiated, its internal values are default, need to be initialized for assignment and other operations, we continue to see its implementation process according to the code. In the instantiation process, there is a method, doCreateBean, which initializes the instantiated object after it has been created. The code is as follows:
// Fill the property populateBean(beanName, MBD, instanceWrapper); // Initialize the bean exposedObject = initializeBean(beanName, exposedObject, MBD);Copy the code
InitializeBean (beanName, exposedObject, MBD) :
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() ! = null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else {// Implement the Aware interface method invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || ! MBD. IsSynthetic ()) {/ / perform before initialization bean beans rear processor wrappedBean = applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName); } try {// Execute the initialization method (XML configuration init-method) invokeInitMethods(beanName, wrappedBean, MBD); } catch (Throwable ex) { throw new BeanCreationException( (mbd ! = null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || ! MBD. IsSynthetic ()) {/ / execution after initialization bean beans rear processor wrappedBean = applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName); } return wrappedBean; }Copy the code
There are several important processes in the code above: 1) Implement methods that implement the Aware interface. 2) Execute the bean’s post-processor before initializing the bean. 3) Perform the initialization method (init-method for XML configuration). 4) Execute the bean’s post-processor after initializing the bean. After passing through the above stages, the entire object completes its initialization process and becomes a complete object. Then its life cycle is as follows: