preface

Spring knowledge summarized an atlas, share with you:

The Spring Bean lifecycle is a common interview question and a technical point often used in daily development. In application development, you often need to perform special initialization work, such as establishing a database connection, opening a network connection, or in some business beans, you want to get the Spring IOC container, Or maybe you want to get some beans that are already instantiated. At the same time, there is some destruction that needs to be done at the end of the service. For working design purposes, Spring IOC provides interfaces that allow application initialization and destruction of custom beans.

Spring Bean life cycle

Take a look at the Spring Bean lifecycle flowchart for subsequent source code analysis.

The Spring Bean life cycle is divided from large nodes into four processes: instantiation, attribute assignment, initialization, and destruction. In daily business development, the two points we should cover most are initialization and destruction, such as the custom Bean implementation InitializingBean and DisposeableBean.

Source code analysis

The Spring IOC container is initialized

Initialization from AbstractAutowireCapableBeanFactory doCreateBean method start, I marked the key points in the corresponding code position

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); If (instanceWrapper == null) {instanceWrapper = this.createBeanInstance(beanName, MBD, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass(); if (beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; } synchronized(mbd.postProcessingLock) { if (! mbd.postProcessed) { try { this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable var17) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17); } mbd.postProcessed = true; } } boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName); if (earlySingletonExposure) { this.addSingletonFactory(beanName, () -> { return this.getEarlyBeanReference(beanName, mbd, bean); }); } Object exposedObject = bean; Try {//2. Assign the property to this.populateBean(beanName, MBD, instanceWrapper); Initializing exposedObject = this.initializeBean(beanName, exposedObject, MBD); } catch (Throwable var18) { if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) { throw (BeanCreationException)var18; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18); } if (earlySingletonExposure) { Object earlySingletonReference = this.getSingleton(beanName, false); if (earlySingletonReference ! = null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (! this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) { String[] dependentBeans = this.getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length); String[] var12 = dependentBeans; int var13 = dependentBeans.length; for(int var14 = 0; var14 < var13; ++var14) { String dependentBean = var12[var14]; if (! this.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 'getBeanNamesOfType' with the 'allowEagerInit' flag turned  off, for example."); Try {}}}} / / 4. Destruction - register callback interface this. RegisterDisposableBeanIfNecessary (beanName, bean, MBD); return exposedObject; } catch (BeanDefinitionValidationException var16) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16); }}Copy the code

To keep the code snippet clean, I removed the Logger code.

As you can see from the code snippet above, the four key points in the late life of Spring that we summarized above are reflected in our analysis of the initialization and destruction processes.

AbstractAutowireCapableBeanFactory.initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { //1. Check Aware related interface and setting depend on / / BeanNameAware, BeanClassLoaderAware, BeanFactoryAware if (System. GetSecurityManager ()! = null) { AccessController.doPrivileged(() -> { this.invokeAwareMethods(beanName, bean); return null; }, this.getAccessControlContext()); } else { this.invokeAwareMethods(beanName, bean); } //2.BeanPostProcessor preprocessing Object wrappedBean = bean; if (mbd == null || ! MBD. IsSynthetic ()) {/ / BeanPostProcessor interface postProcessBeforeInitialization callback wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName); } //3. If the InitializingBean interface is implemented, afterPropertiesSet() //4 is called. If a custom init-method() is configured, run this command. try { this.invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable var6) { throw new BeanCreationException(mbd ! = null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6); } / / 5. BeanPostProcessor rear handle the if (MBD = = null | |! MBD. IsSynthetic ()) {/ / BeanPostProcessor interface postProcessAfterInitialization callback wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }Copy the code

AbstractAutowireCapableBeanFactory.invokeAwareMethods

InvokeAwareMethod is an interface that invokes a series of Aware endings, such as BeanNameAware, ApplicationContextAware, and BeanFactoryAware.

private void invokeAwareMethods(String beanName, Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware)bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = this.getBeanClassLoader(); if (bcl ! = null) { ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware)bean).setBeanFactory(this); }}}Copy the code

AbstractAutowireCapableBeanFactory.invokeInitMethods

InvokeinitMethods is simply calling afterPropertiesSet of the InitializingBean interface and checking for custom init-Method.

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = bean instanceof InitializingBean; if (isInitializingBean && (mbd == null || ! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (System.getSecurityManager() ! = null) { try { AccessController.doPrivileged(() -> { ((InitializingBean)bean).afterPropertiesSet(); return null; }, this.getAccessControlContext()); } catch (PrivilegedActionException var6) { throw var6.getException(); } } else { ((InitializingBean)bean).afterPropertiesSet(); } } if (mbd ! = null && bean.getClass() ! = NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && (! isInitializingBean || !" afterPropertiesSet".equals(initMethodName)) && ! mbd.isExternallyManagedInitMethod(initMethodName)) { this.invokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code

The Spring IOC container creates beans by instantiating them, destroying them, and implementing BeanPostProcessor interface methods. Let’s look at the Spring container destruction phase.

Container to destroy

The Spring container destroys the procedure call chain

Spring uses adapter mode here, which means the final destruction task is taken care of by the DisposableBeanAdapter. Let’s take a look at the structure of the DisposeableBeanAdapter.

You can see from the structure that the bean property type is Object, which is the bean to be destroyed, and the beanName property.

public void destroy() { if (! CollectionUtils.isEmpty(this.beanPostProcessors)) { Iterator var1 = this.beanPostProcessors.iterator(); while(var1.hasNext()) { DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next(); processor.postProcessBeforeDestruction(this.bean, this.beanName); } } if (this.invokeDisposableBean) { try { if (System.getSecurityManager() ! = null) { AccessController.doPrivileged(() -> { ((DisposableBean)this.bean).destroy(); return null; }, this.acc); } else { ((DisposableBean)this.bean).destroy(); } } catch (Throwable var3) { } } if (this.destroyMethod ! = null) { this.invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName ! = null) { Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName); if (methodToInvoke ! = null) { this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); }}}Copy the code

conclusion

The Spring Bean life cycle is divided into four phases and multiple extension points, which are divided into affecting multiple beans and individual beans. There are four stages: instantiation, attribute assignment, initialization, and destruction.

The extension point

Affecting multiple beans

1.BeanPostProcessor

2.InstantiationAwareBeanPostProcessor

Affecting individual beans

1.BeanNameAware

2.BeanFactoryAware

3.BeanClassLoaderAware

4.ApplicationContextAware

Two key interfaces in the Spring lifecycle: InitializingBean, DisposableBean.

The last

I have compiled a Spring related information document, Spring series of family drum, Java systematic information (including Java core knowledge, interview topics and 21 years of the latest Internet real questions, e-books, etc.), friends who need to pay attention to the public number [procedures yuan Small wan] can obtain.