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 >.