The life cycle of a Bean can be divided into four steps
- Bean instantiation
- Bean attribute assignment
- Bean initialization
- Destroy
In traditional Java applications, the life cycle of a Bean is very simple. Instantiate a Bean using the Java keyword new, and then the Bean can be used. Once the Bean is no longer used, Java automatically garbage collects it. The life cycle of Spring managed beans is much more complex. The life cycle of beans is still a hot issue in Spring interview.
The following is an approximate bean life cycle flow chart drawn according to the source code. The main logic of the bean life cycle is in the doCreateBean() method of the AbstractAutowireCapableBeanFactory class. Bean instantiation, attribute assignment and initialization are executed in order
When instantiating a Bean, appropriate instantiation methods will be selected according to conditions, such as factory method, instantiation of structure with parameters and instantiation of structure without parameters,
// Partial source code protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { if (instanceWrapper == null) { //Create bean instantiation and use appropriate instantiation strategies to create new instances: factory methods, automatic constructor injection, and simple initialization.. instanceWrapper = createBeanInstance(beanName, mbd, args); } }
Enter the method of creating Bean instance and call the required instantiation strategy
// Part of the source code in createbean instance protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { //Resolve the class object of the current bean from the bean definition Class<?> beanClass = resolveBeanClass(mbd, beanName); /** * This method is newly added in spring 5.0. If there is a Supplier callback, the given callback method is used to initialize the policy */ Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } /** * Factory method. If we configure it through the configuration class, the factory method is adopted, and the method name is tulingDao, which is the name of our factory method * @Bean The instance is created here */ if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } //If parsed if (resolved) { if (autowireNecessary) { //Reflection call through a constructor with parameters return autowireConstructor(beanName, mbd, null, null); } else { //Call the parameterless constructor to create the object return instantiateBean(beanName, mbd); } } /** * Select the appropriate constructor object through the bean's post processor */ Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); /** * If the BeanPostProcessor is customized, the constructor or * Automatic assembly mode using constructor or * The BeanDefinition constructor parameter is set, or * There are parameters: args in getBean(String name, Object... args) * Is initialized with a custom constructor */ if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //Creating objects through constructors return autowireConstructor(beanName, mbd, ctors, args); } //Creates an object using a parameterless constructor call return instantiateBean(beanName, mbd); }
Assign the attribute after the Bean is instantiated, and call populateBean(beanName, mbd, instanceWrapper); Method for attribute assignment and attribute injection according to different methods
// Partial source code protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { /** * Determine the attribute injection model of our bean * AUTOWIRE_BY_NAME Inject by name * AUTOWIRE_BY_TYPE Injection according to type */ if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { //Encapsulate PropertyValues into MutablePropertyValues MutablePropertyValues newPvs = new MutablePropertyValues(pvs); //Inject according to the attribute name of the bean if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } //Inject according to the type of bean if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } //Overwrite the processed attributes with the original ones pvs = newPvs; } }
After attribute injection, initializeBean(beanName, exposedObject, mbd) is called. Method to initialize the Bean.
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 { //If our bean implements the XXXAware interface, we can call back the method invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //Call the postProcessorsBeforeInitialization method of our bean's post processor wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //Call initialization method invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //Call the PostProcessorsAfterInitialization method of our bean's postprocessor wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
Looking at the source code, we can find that invokeawaremethods (bean name, bean) will be called before calling the real initialization method; To detect whether the XXXAware interface is implemented
Step: call setBeanName method of BeanNameAware interface, call setBeanClassLoader method of BeanClassLoaderAware, call setBeanFactory method of beanfactory aware, and the source code is as follows
private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { //Our bean implements BeanNameAware if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } //The BeanClassLoaderAware interface is implemented if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } //Beanfactory aware is implemented if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
Call your own initialization method
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { //Determine whether the InitializingBean interface is implemented in our container boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //Callback the afterpropertieset() method of InitializingBean ((InitializingBean) bean).afterPropertiesSet(); } } // Call initMethod if (mbd != null && bean.getClass() != NullBean.class) { //Let's see if there is an init method defined in beanclass String initMethodName = mbd.getInitMethodName(); //Judge whether the custom init method name is not called afterpropertieset if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //Call our own initialization method invokeCustomInitMethod(beanName, bean, mbd); } } }
After the bean is instantiated, it will call the PostProcessorsAfterInitialization method of the post processor of our bean. When this method is executed, it will create a proxy object for the class that needs a proxy, that is, AOP proxy
if (mbd == null || !mbd.isSynthetic()) { //Call the PostProcessorsAfterInitialization method of our bean's postprocessor wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; //Get the post processor of all bean s in our container for (BeanPostProcessor processor : getBeanPostProcessors()) { /** * * What is implemented here is the postProcessAfterInitialization of the BeanPostProcessor interface to generate our proxy object */ Object current = processor.postProcessAfterInitialization(result, beanName); //If only one of them returns null, the original is returned directly if (current == null) { return result; } result = current; } return result; }
After Bean initialization, it can be used.
summary
- When Spring starts, find the beans that need to be managed by Spring for instantiation
- After instantiation, inject attributes into the Bean
- If the Bean implements the BeanNameAware interface, Spring passes the Id of the Bean to the setBeanName() method
- If the Bean implements the BeanClassLoaderAware interface, Spring will call the setBeanClassLoader() method
- If the Bean implements the BeanFactory aware interface, Spring will call the setBeanFactory() method to pass in the BeanFactory container instance
- If beans implement the BeanPostProcessor interface, Spring will call their postProcessBeforeInitialization() method
- If beans implement the InitializingBean interface, Spring will call their afterpropertieset () method
- If beans implement the BeanPostProcessor interface, Spring will call their postProcessAfterInitialization() method
- If the bean implements the DisposableBean interface, Spring will call its destroy () interface method. Similarly, if the bean uses the destroy method declaration, the method will also be called