In the previous article, we looked at step 5 in doCreateBean() : property population in detail, and this article continues with step 6 in doCreateBean() : initializing the bean instance object

This article is transferred from the public number: impression channel source

Let’s review the main flow of CreateBean:

  1. If it is singleton mode, get the BeanWrapper instance object from the factoryBeanInstanceCache cache and remove the cache
  2. callcreateBeanInstance()Instantiate the bean
  3. Post processing
  4. Singleton pattern for loop dependency processing
  5. fill
  6. Initialize the bean instance object
  7. Depend on the check
  8. Register the bean’s destruction method

1. Initialization

After filling the Bean with properties, Spring initializes the Bean as follows:

//AbstractAutowireCapableBeanFactory.java

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	// The JDK's security mechanism validates permissions
	if(System.getSecurityManager() ! =null) {
		// <1> Activate the Aware method to handle special beans: Aware, BeanClassLoaderAware, BeanFactoryAware
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		// <1> Activate the Aware method to handle special beans: Aware, BeanClassLoaderAware, BeanFactoryAware
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	// <2> postprocessor, before
	if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }// <3> Activate the user-defined init method
	try {
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	// <2> after
	if (mbd == null| |! mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }return wrappedBean;
	}
Copy the code

The method of initializing the bean is actually three steps, and these three steps are mainly initialized according to user Settings. These three steps are:

  • <1> Activate the Aware method.

  • <2> Rear processor.

  • <3> Custom init method.

1.1, Aware

Aware, English translation is Aware of, Aware of. Spring provides a number of Aware interfaces to assist Spring beans in programmatically calling the Spring container, and you can enhance the functionality of Spring beans by implementing these interfaces.

Spring provides the following series of Aware interfaces:

LoadTimeWeaverAware: the Spring Bean is loaded into a third party module, such as AspectJ BeanClassLoaderAware: the Spring Bean is loaded into the class loader BootstrapContextAware: Resource adapter BootstrapContext, such as JCA and CCI ResourceLoaderAware: the loader that accesses resources at the bottom level BeanFactoryAware: declares BeanFactory PortletConfigAware: PortletConfig PortletContextAware: PortletContext ServletConfigAware: ServletConfig ServletContextAware: ServletContext MessageSourceAware: internationalization ApplicationEventPublisherAware: application events NotificationPublisherAware: JMX notifies BeanNameAware: Declare the name of the Spring Bean

Aware is quite complicated, and I will study this content in the future. I won’t talk more about it here.

1.2. Rear processor

BeanPostProcessor, encountered several times in the previous bean loading process, is used to: If we want to add some of our own logic after the Spring container completes Bean instantiation, configuration, and other initialization, use this interface, which gives the user ample authority to change or extend Spring. Is an essential interface for our extension and enhancement of Spring.

ApplyBeanPostProcessorsBeforeInitialization () method, the code is as follows:

// AbstractAutowireCapableBeanFactory.java

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {
    Object result = existingBean;
    // Iterate through the BeanPostProcessor array
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        / / processing
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        // Return null, return result
        if (current == null) {
            return result;
        }
        / / change the result
        result = current;
    }
    return result;
}
Copy the code

ApplyBeanPostProcessorsAfterInitialization () method, the code is as follows:

// AbstractAutowireCapableBeanFactory.java

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {
    Object result = existingBean;
    / / traverse BeanPostProcessor
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        / / processing
        Object current = processor.postProcessAfterInitialization(result, beanName);
        // Return null, return result
        if (current == null) {
            return result;
        }
        / / change the result
        result = current;
    }
    return result;
}
Copy the code

The logic is to get the defined BeanPostProcessor using the getBeanPostProcessors() method, Then call its respectively postProcessBeforeInitialization () and postProcessAfterInitialization () method, customized business process.

1.3. Customize init methods

The configuration of a < bean > tag in XML, init-method, allows us to perform some of our own custom logic when the bean is initialized. This is where it is triggered, with the following code:

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    // If InitializingBean is an InitializingBean, afterPropertiesSet() is called.
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null| |! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if(System.getSecurityManager() ! =null) { // Safe mode
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    // <1> property initialization processing
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            } catch (PrivilegedActionException pae) {
                throwpae.getException(); }}else {
            // <1> property initialization processing((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)) {// <2> Activates the user-defined initialization methodinvokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code

First, check if it is InitializingBean. If so, you need to execute the afterPropertiesSet() method, because in addition to customizing the initialization method with init-method, you can also implement the InitializingBean interface. The interface has only one afterPropertiesSet() method. <1> #afterPropertiesSet() method followed by <2> init-method.