This is the fourth day of my participation in Gwen Challenge

For Java programmers, the Spring framework is always a hot topic in an interview, and the spring bean lifecycle is one of the most popular questions in a series of interviews. Today we are going to look at the life cycle of Spring beans.

Take a look at the overall flow chart:

I believe that many people have more or less seen this similar flow chart on the Internet, but it looks particularly tedious, not easy to remember.

According to my personal understanding, the life cycle of Spring beans can be divided into four stages:

  1. Instantiation of beans (generating objects through Java reflection)
  2. Bean property assignment (PopulateBean () is a stage that involves a lot of problems, such as loop dependency and how Spring is solved by the design of the three-level cache. You can talk about it in the interview.)
  3. Initialization of beans (InitializeBeans)
  4. The destruction of the bean

The destruction of the above process in addition to the fourth bean, almost all the rest of the logic in the org. Springframework. Beans. Factory. Support. AbstractAutowireCapableBeanFactory# doCreateBean method:

Look at the source

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
    if (instanceWrapper == null) {
    // instantiate the object inside the second call to the post-processor
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // Initialize the bean instance.
    Object exposedObject = bean;
    // Attribute fill, also known as automatic injection
    // The fifth and sixth post-processor calls are completed
    populateBean(beanName, mbd, instanceWrapper);
    // Initialize Spring
    // The seventh and eighth post-processor calls are made
    exposedObject = initializeBean(beanName, exposedObject, mbd);
}
Copy the code

Irrelevant code is ignored

What extensibility enhancements are made in the diagram after the bean’s properties are populated, but before initialization? Take a look at the source code as usual:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if(System.getSecurityManager() ! =null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        invokeAwareMethods(beanName, bean);
                        return null;
                }, getAccessControlContext());
        }
        else {
                // Call the relevant methods of the Aware interface
                invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null| |! mbd.isSynthetic()) {// Call BeanPostProcessor's preprocessing method
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
                // Call the InitMehod method
                invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
                throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
                                beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null| |! mbd.isSynthetic()) {// The post-processing method that calls BeanPostProcessor is implemented here
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
}
Copy the code

It is clear from the source code what is done before the bean is actually initialized

  1. InvokeAwareMethods (beanName, bean); (BeanName, BeanFactory, BeanClassLoader)
private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if(bcl ! =null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); }}if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); }}}Copy the code
  1. Invoke the BeanPostProcessor pre-processing methods applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName);
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessBeforeInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
        }
        return result;
}
Copy the code
  1. InvokeInitMethods (beanName, wrappedBean, MBD);
protected void invokeInitMethods(String beanName, final 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((PrivilegedExceptionAction<Object>) () -> {
                // If InitializingBean interface is implemented, execute its afterPropertiesSet method
                                        ((InitializingBean) bean).afterPropertiesSet();
                                        return null;
                                }, getAccessControlContext());
                        }
                        catch (PrivilegedActionException pae) {
                                throwpae.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)) {// Perform a custom initialization methodinvokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code
  1. Call BeanPostProcessor rear processing method: applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName);
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
}
Copy the code

The bean’s initialization is then saved in the Spring application context and can be called as a getBean until it is closed and destroyed.

Above, thanks for reading.