Spring core source code learning - IoC load Bean: create the initialization Bean object of the Bean

1. initializeBean

// AbstractAutowireCapableBeanFactory.java

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) { // safe mode
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            // <1> Activate Aware method to handle special beans: Aware, BeanClassLoaderAware, beanfactory Aware
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    } else {
        // <1> Activate Aware method to handle special beans: Aware, BeanClassLoaderAware, beanfactory Aware
        invokeAwareMethods(beanName, bean);
    }

    // <2> Post processor, before
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    // <3> Activate user-defined init method
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }

    // <2> after processor
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

The method of initializing bean s is actually a three-step process, and these three steps are mainly initialized according to user settings. The three processes are:

<1> Activate Aware method.
<3> Application of post processor.
<2> Activate the custom init method.

1.1 method of activating Aware

Aware, English translation is conscious and perceptive. Spring provides many aware interfaces to assist spring beans to call spring containers programmatically. By implementing these interfaces, you can enhance the functions of spring beans.

Spring provides the following series of Aware interfaces:

Loadtimeweaver aware: when loading spring beans, weave in third-party modules, such as AspectJ
BeanClassLoaderAware: class loader for loading spring beans
BootstrapContextAware: resource adapter BootstrapContext, such as JCA and CCI
ResourceLoaderAware: the loader that accesses resources at the bottom
BeanFactory aware: declare BeanFactory
PortletConfigAware: PortletConfig
PortletContextAware: PortletContext
ServletConfigAware: ServletConfig
ServletContextAware: ServletContext
MessageSourceAware: Internationalization
ApplicationEventPublisherAware: application events
NotificationPublisherAware: JMX notifications
BeanNameAware: declares the name of the Spring Bean

#invokeAwareMethods(final String beanName, final Object bean), the code is as follows:

// AbstractAutowireCapableBeanFactory.java

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

1.2 application of post processor

BeanPostProcessor has encountered the bean loading process many times before. I believe you are no stranger. This is an essential highlight of the open framework in Spring.

The function of BeanPostProcessor is: if we want to add some logic processing after the Spring container completes Bean instantiation, configuration and other initialization, please use this interface. This interface gives users sufficient permission to change or extend Spring. It is an essential interface for us to extend and enhance Spring.

#applyBeanPostProcessorsBeforeInitialization(...) method, the code is as follows:

// AbstractAutowireCapableBeanFactory.java

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {
    Object result = existingBean;
    // Traversing the BeanPostProcessor array
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        // handle
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        // If NULL is returned, result is returned
        if (current == null) {
            return result;
        }
        // Modify result
        result = current;
    }
    return result;
}

#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()) {
        // handle
        Object current = processor.postProcessAfterInitialization(result, beanName);
        // If NULL is returned, result is returned
        if (current == null) {
            return result;
        }
        // Modify result
        result = current;
    }
    return result;
}

In fact, the logic is to obtain the defined BeanPostProcessor through the #getBeanPostProcessors() method, and then call its #postProcessBeforeInitialization(...), #postProcessAfterInitialization(...) methods respectively for custom business processing.

1.3 activate custom init method

If you are familiar with the tag configuration, you must not forget the init method method, which is executed here. The code is as follows:

// AbstractAutowireCapableBeanFactory.java

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    // First, we will check whether it is InitializingBean. If so, we need to call afterpropertieset()
    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) {
                throw pae.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> Activate user-defined initialization method
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}
  • First, check whether it is InitializingBean. If so, we need to execute #afterpropertieset () method, because we can not only use init method to customize the initialization method, but also implement the InitializingBean interface. Interface has only one #afterpropertieset() method.
  • The execution order of the two methods is the method corresponding to the #afterpropertieset() method of < 1 > and then the init method of < 2 >.

Keywords: Spring

Added by OM2 on Wed, 19 Jan 2022 20:56:41 +0200