Bean的生命周期

342 阅读4分钟

Bean是Spring中最核心的东西,因为Spring就像是个大水桶,而Bean就像容器中的水,水桶脱离了水便也没有了用处。Bean没有任何特别之处,Spring的目的就是让我们的Bean能成为一个纯粹的POJO,这也是Spring所追求的。那么Bean的整个生命周期是个什么样子的呢?

Bean创建过程

Spring Bean的整体创建流程如下:

  • 定义普通的JAVA类
  • 将普通的JAVA类转化成Bean的定义-BeanDefinition
  • 根据BeanDefinition创建出Spring Bean

image.png

这个地方肯定有一个疑问,为什么不能用class对象来创建Bean呢?因为在class对象仅仅能描述一个对象的创建,它不足以用来描述一个Spring bean,而对于是否为懒加载、是否是首要的、初始化方法是哪个、销毁方法是哪个,这个Spring中特有的属性在class对象中并没有,所有Spring就定义了BeanDefinition来完成bean的创建。

源码解析

我们想要将某些文件夹下的类放到Spring容器中去,简单的写法:

public static void main(String[] args) {
   AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

   UserService userService = (UserService) context.getBean("userService");
   userService.test();

   /*AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
   context.register(AppConfig.class);
   context.refresh();*/
}

在跟踪AnnotationConfigApplicationContext的源码中,关键的一个方法是AbstractApplicationContext类中的refresh方法,这个方法中的内容就可以总结成上边的图Bean创建的整个过程,方法中具体的内容:

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      // 这里会判断能否刷新,并且返回一个BeanFactory, 刷新不代表完全情况,主要是先执行Bean的销毁,然后重新生成一个BeanFactory,再在接下来的步骤中重新去扫描等等
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      // 准备BeanFactory
      // 1. 设置BeanFactory的类加载器、SpringEL表达式解析器、类型转化注册器
      // 2. 添加三个BeanPostProcessor,注意是具体的BeanPostProcessor实例对象
      // 3. 记录ignoreDependencyInterface
      // 4. 记录ResolvableDependency
      // 5. 添加三个单例Bean
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         // 子类来设置一下BeanFactory
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

         // Invoke factory processors registered as beans in the context.
         // BeanFactory准备好了之后,执行BeanFactoryPostProcessor,开始对BeanFactory进行处理
         // 默认情况下:
         // 此时beanFactory的beanDefinitionMap中有6个BeanDefinition,5个基础BeanDefinition+AppConfig的BeanDefinition
         // 而这6个中只有一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor
         // 这里会执行ConfigurationClassPostProcessor进行@Component的扫描,扫描得到BeanDefinition,并注册到beanFactory中
         // 注意:扫描的过程中可能又会扫描出其他的BeanFactoryPostProcessor,那么这些BeanFactoryPostProcessor也得在这一步执行
         invokeBeanFactoryPostProcessors(beanFactory);  // scanner.scan()

         // Register bean processors that intercept bean creation.
         // 将扫描到的BeanPostProcessors实例化并排序,并添加到BeanFactory的beanPostProcessors属性中去
         registerBeanPostProcessors(beanFactory);

         beanPostProcess.end();

         // Initialize message source for this context.
         // 设置ApplicationContext的MessageSource,要么是用户设置的,要么是DelegatingMessageSource
         initMessageSource();

         // Initialize event multicaster for this context.
         // 设置ApplicationContext的applicationEventMulticaster,么是用户设置的,要么是SimpleApplicationEventMulticaster
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 给子类的模板方法
         onRefresh();

         // Check for listener beans and register them.
         // 把定义的ApplicationListener的Bean对象,设置到ApplicationContext中去,并执行在此之前所发布的事件
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
         contextRefresh.end();
      }
   }
}

整个创建过程细化后的流程如下图:

image.png

参考了一些文章,Spring Bean的生命周期大致被分为了四个阶段,而在每个阶段的前后都会有很多的扩展点提供给你,方便你对不同流程时期的Bean做一些额外的操作,具体的内容本次不做介绍,后续会深入:

  • 实例化 Instantiation
  • 属性赋值 Populate
  • 初始化 Initialization
  • 销毁 Destruction

总结

原来换工作面试被问到Spring底层原理时很多的知识点都是百度上的流程图了解到的,回答时还是很心虚的,只是理解了Spring的表层,最精髓的内容还没有挖掘出来。最近断断续续的看了一段时间的Spring源码,真的体会到了其中的“深奥”,在使用的过程中,虽然我们只是简单的定义类,以及使用相关的注解或者配置文件就可以让程序跑起来,但这却是是Spring底层做了大量的工作来支撑我们的使用,真的很强大。

不积小流无以成江海,不积跬步无以至千里;知识的获取过程,有些时候需要我们静下心来,仔细认真的去研究、总结;源码解读的过程还很长,期待。