目录
Spring Bean 的生命周期
/    

Spring Bean 的生命周期

Spring Bean 的生命周期

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

在这个方法内打上 debug 断点,可以看到 IDEA 上的调用链

image.png

通过一点一点向上打断点,可以找到

protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch (this.webApplicationType) { case SERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }

通过这个方法,由于当前应用已经确定是 SERVLET, contextClass 对应的值是 org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext

然后就是通过反射进行实例化

通过无参构造,调用了父类的无参构造方法,创建了 BeanFactory 的实例

public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }

==// TODO==

实例化

  • 创建 Bean 实例

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

  • 设置属性值,Spring 容器注入必要的属性到 Bean 中

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

  • 检查 Aware

    如果 Bean 实现了 BeanNameAware、BeanClassLoaderAware 等这些 Aware 接口,Spring 容器会调用它们。

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

    if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); }
    private void invokeAwareMethods(String beanName, 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); } } }
  • 调用 BeanPostProcessor 的前置处理方法

    在 Bean 初始化之前,允许自定义的 BeanPostProcessor 对实例进行处理,如修改 Bean 的状态,BeanPostProcessor 的 postProcessorsBeforeInitialization 方法此时会被调用。

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

    @Override 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; }

初始化

  • 调用 InitializingBean 的 afterPropertiesSet 方法。

    提供一个机会,在所有 Bean 属性设置完毕后进行初始化操作。如果出现了Bean 实现了 InitializingBean 接口,afterPropertiesSet 方法会被调用。

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

    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) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } }
  • 调用自定义 init-method 方法

    提供一种配置方式,在 XML 配置中指定 Bean 的初始化方法。如果 Bean 在配置文件中定义了初始化方法,那么该方法会被调用。

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

    if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } }

    检查initMethodName是否不为空(StringUtils.hasLength(initMethodName)),并且不是标准的InitializingBean接口的afterPropertiesSet方法("afterPropertiesSet".equals(initMethodName)),同时确保这个方法不是由外部管理的(mbd.isExternallyManagedInitMethod(initMethodName))。

    这些检查确保了只有用户自定义的初始化方法才会被调用。

  • 调用 BeanPostProcessor 的后置处理方法

    在 Bean 初始化之后,再次允许 BeanPostProcessor 对 Bean 进行处理。BeanPostProcessor 的 postProcessorsAfterInitialization 方法会在此时被调用。

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

    @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; }

注册 Destruction 回调

  • 注册 Destruction 回调

    如果 Bean 实现了 DisposableBean 接口或者在 Bean 中定义了自定义的销毁方法,Spring 容器会为这些 Bean 注册一个销毁回调,确保在容器关闭时能够正确清理资源。

    org.springframework.beans.factory.support.AbstractBeanFactory#registerDisposableBeanIfNecessary

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null); if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { if (mbd.isSingleton()) { // Register a DisposableBean implementation that performs all destruction // work for the given bean: DestructionAwareBeanPostProcessors, // DisposableBean interface, custom destroy method. // 用于将给定的Bean名称和DisposableBean实例注册到容器中。这样,当容器关闭时,这些Bean将被自动销毁。 // 当容器关闭时,DisposableBeanAdapter的destroy方法将被调用。这个方法首先会应用所有的BeanPostProcessor,然后调用DisposableBean的destroy方法或者通过反射调用在BeanDefinition中指定的销毁方法。 registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); } else { // A bean with a custom scope... Scope scope = this.scopes.get(mbd.getScope()); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); } scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); } } }

Bean 的正常使用

  • 到此,Bean 已经完全初始化,可以开始处理应用程序的请求了。

Bean 的销毁

  • 调用 DestructionAwareBeanPostProcessor 的 postProcessorBeforeDestruction 方法

    创建 DisposableBeanAdapter 的时候,通过传的 postProcessors 筛选出 DestructionAwareBeanPostProcessor

  • 调用 DisposableBean 的 destroy 方法

    当容器关闭时,如果 Bean 实现了 DisposableBean 接口,destroy 方法将会被调用。

    org.springframework.beans.factory.support.DisposableBeanAdapter#destroy

    if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((DisposableBean) this.bean).destroy(); return null; }, this.acc); } else { ((DisposableBean) this.bean).destroy(); }
  • 调用自定义的 destroy-method

    如果 Bean 在配置文件中配置了销毁方法,那么该方法会被调用。

    org.springframework.beans.factory.support.DisposableBeanAdapter#destroy

    if (this.destroyMethod != null) { invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); if (methodToInvoke != null) { invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); } }

最后

总结一下:

创建实例、

属性填充、

检查Aware、

执行 postProcessorsBeforeInitialization 方法、

执行 InitializingBean 的 afterPropertiesSet 方法、

执行自定义 init 方法、

执行 postProcessorsAfterInitialization 方法、

注册 Destruction 回调、

执行销毁方法(DisposableBeanAdapter)、

执行自定义的销毁方法

文本内容摘抄自 Hollis 八股文。


标题:Spring Bean 的生命周期
作者:gitsilence
地址:https://blog.lacknb.cn/articles/2024/03/26/1711441534086.html

Gitalking ...