springboot(4) 启动过程及实现对bean动态代理源码分析

1.springboot启动过程分析

  • springboot启动过程run方法:
public ConfigurableApplicationContext run(String... args) {
  //创建一个StopWatch对象并调用它的start方法,该类是Spring提供的一个计时器类
  StopWatch stopWatch = new StopWatch();
  stopWatch.start();
  
  ConfigurableApplicationContext context = null;
  FailureAnalyzers analyzers = null;
  
  //设置系统属性java.awt.headless,这里设置为true,表示运行在服务器端
  configureHeadlessProperty();
  
  /**
   * 获取SpringApplicationRunListeners对象,这个对象是一个SpringBoot事件广播器的管理者,
   * 它主要是管理SpringApplicationRunListener对象的,
   * SpringApplicationRunListener接口规定了SpringBoot的生命周期,并在各个生命周期广播相应的事件
   * springboot默认为EventPublishingRunListener
   * 具体可见另外一篇博文springboot(2)生命周期和监听器。
   */
  SpringApplicationRunListeners listeners = getRunListeners(args);
  //广播启动事件
  listeners.starting();
  
  try {
   ApplicationArguments applicationArguments = new DefaultApplicationArguments(
     args);
   
   //准备运行的环境,比如开发环境dev,测试环境test然后根据环境解析不同的配置文件,并广播环境准备事件
   ConfigurableEnvironment environment = prepareEnvironment(listeners,
     applicationArguments);
   
   //打印SpringBoot的LOGO
   Banner printedBanner = printBanner(environment);
   
   //创建SpringBoot的上下文 判断当前是否是web环境,
   //如果是web程序,创建AnnotationConfigEmbeddedWebApplicationContext的实例,
   //否则创建AnnotationConfigApplicationContext的实例
   context = createApplicationContext();
   
   //创建FailureAnalyzers的对象,主要是用来处理启动时发生一些异常时的一些分析
   analyzers = new FailureAnalyzers(context);
   
   //准备上下文
   prepareContext(context, environment, listeners, applicationArguments,
     printedBanner);
   //刷新上下文
   refreshContext(context);
   afterRefresh(context, applicationArguments);   //发送启动完成事件
   listeners.finished(context, null);
   stopWatch.stop();
   if (this.logStartupInfo) {
    new StartupInfoLogger(this.mainApplicationClass)
      .logStarted(getApplicationLog(), stopWatch);
   }
   return context;
  }
  catch (Throwable ex) {
   handleRunFailure(context, listeners, analyzers, ex);
   throw new IllegalStateException(ex);
  }
 }
  • 准备运行的环境
private ConfigurableEnvironment prepareEnvironment(
   SpringApplicationRunListeners listeners,
   ApplicationArguments applicationArguments) {
 
  // 检查之前设置的webEnvironment属性,如果是web程序,那么创建一个StandardServletEnvironment对象,否则创建StandardEnvironment对象
  ConfigurableEnvironment environment = getOrCreateEnvironment();
 
  //准备运行环境配置,根据环境,比如开发环境dev,加载相关配置文件
  configureEnvironment(environment, applicationArguments.getSourceArgs());
 
  //发布运行环境加载完毕的事件
  listeners.environmentPrepared(environment);
  if (!this.webEnvironment) {
   environment = new EnvironmentConverter(getClassLoader())
     .convertToStandardEnvironmentIfNecessary(environment);
  }
  return environment;
 }
  • 准备上下文:
private void prepareContext(ConfigurableApplicationContext context,
   ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
   ApplicationArguments applicationArguments, Banner printedBanner) {
  //设置上下文环境
  context.setEnvironment(environment);
 
  //设置上下文的beanNameGenerator和resourceLoader(如果SpringApplication有的话)
  postProcessApplicationContext(context);
 
  //利用初始化器,对上下文做初始化
  //具体可见另外一篇博文 springboot (3)应用上下文初始化器ApplicationContextInitializer
  applyInitializers(context);
  //发布上下文准备好的事件
  listeners.contextPrepared(context);
 
  //打印启动日志
  if (this.logStartupInfo) {
   logStartupInfo(context.getParent() == null);
   logStartupProfileInfo(context);
  }

  //向上下文的beanFactory中注册一个singleton的bean,bean的名字是springApplicationArguments,
  //bean的实例是之前实例化的ApplicationArguments对象
  context.getBeanFactory().registerSingleton("springApplicationArguments",
    applicationArguments);
  //向上下文的beanFactory中注册一个singleton的bean,bean的名字是springBootBanner,bean的实例就是这个printedBanner
  if (printedBanner != null) {
   context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
  }

  //向上下文注册启动类的bean,也就是调用SpringApplication.run(Application.class, args);的类,这里只有一个
  Set sources = getSources();
  Assert.notEmpty(sources, "Sources must not be empty");
  load(context, sources.toArray(new Object[sources.size()]));
 
  //发布上下文加载完毕事件
  listeners.contextLoaded(context);
 }
  • 刷新上下文
public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
   //为刷新上下文信息做准备。例如清空缓存,初始化属性信息,验证必要的属性等
   prepareRefresh();

   //获取到beanFactory,把refreshed属性设置成true,表示已经刷新了,下次再刷新就会抛出异常,不允许重复刷新,
   //然后给beanFactory设置serializationId,就是之前通过ContextIdApplicationContextInitializer生成的id
   //然后通过getBeanFactory方法拿到上下文的beanFactory(之前创建上下文的时候,创建了一个DefaultListableBeanFactory对象)
   ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

   //对beanFactory设置相关参数
   prepareBeanFactory(beanFactory);

   try {
    //为beanFactory添加后置处理器WebApplicationContextServletContextAwareProcessor,并忽略ServletContextAware
    postProcessBeanFactory(beanFactory);

    //扫描路径下的所有类,如果被@Component等注解的类,生成BeanDefinition对象,并回调BeanFactoryPostProcessor后置处理器
    invokeBeanFactoryPostProcessors(beanFactory);

    //注册bean的后置处理器,这些后置处理器将在bean的创建过程中被调用
    registerBeanPostProcessors(beanFactory);

    //初始化上下文的消息源
    initMessageSource();

    //初始化事件广播器,springboot在广播事件的时候,默认是同步的,如果想要实现事件异步传播,
    //就需要自定义一个名叫applicationEventMulticaster的bean,
    //这里就是看是否有自定义的bean,如果有则用用户创建的,否则就用默认的。
    initApplicationEventMulticaster();

    //初始化其他特殊的bean,比如创建serverlet容器相关的bean(TomcatEmbeddedServletContainerFactory)
    onRefresh();

    //想事件广播器中添加各种事件监听器
    registerListeners();

    //实例化所有单例bean
    finishBeanFactoryInitialization(beanFactory);

    //发布容器事件,结束刷新过程
    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();
   }
  }
 }
  • 对beanFactory设置相关参数prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  //设置用于加载bean的类加载器
  beanFactory.setBeanClassLoader(getClassLoader());
  //设置可以解析bean表达式的 表达式解析器 (使用"#{xxx}"配置的属性)
  beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  //添加属性注册器
  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

  //添加ApplicationContextAwareProcessor后置处理器
  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
 
  //设置了6个忽略自动注入的接口,为什么要忽略呢?因为上一步添加的ApplicationContextAwareProcessor,会在bean初始化前后调用相应的方法,
  //而相应的方法里有如下6个设置对应的接口
  beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
  beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
  beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

  //设置了几个自动装配的特殊规则,如果注入的是BeanFactory类型,则注入beanFactory对象,
  //如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext类型,则注入当前对象(Spring上下文 - context)
  beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  beanFactory.registerResolvableDependency(ApplicationContext.class, this);

  //注册ApplicationListenerDetector,应用监听检查器,
  //该检测器的主要作用是在bean初始化后,会检查该bean是否是ApplicationListener,
  //如果是,那么会验证它是否是单例,如果不是单例,那么删除singletonNames中对应的key,singletonNames中记录了bean的名称及是否是单例
  beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

  // Detect a LoadTimeWeaver and prepare for weaving, if found.
  if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
   beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
   // Set a temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }

  //注册几个特殊的bean
  if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
   beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
  }
  if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
   beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
  }
  if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
   beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
  }
 }

run方法步骤总结:
    1.获取spring应用执行监听器(SpringApplicationRunListeners)
    2.利用spring应用执行监听器广播启动事件
    3.准备运行的环境(dev,test),根据环境解析不同的配置文件
         3.1 检查webEnvironment属性,如果是web程序,那么创建一个StandardServletEnvironment对象,否则创建StandardEnvironment对象
         3.2 准备运行环境配置,根据环境(dev,test),加载相关配置文件
         3.3 利用spring应用执行监听器广播运行环境加载完毕的事件
    4.创建spring应用上下文,如果是web程序,创建web应用上下文实例
    5.准备spring应用上下文
        5.1 利用spring初始化器,对上下文做初始化操作
        5.2 利用spring应用执行监听器广播上下文准备好的事件
        5.3 向beanFactory注册springApplicationArguments和springBootBanner单例bean
        5.4 向上下文注册启动类的bean,也就是调用SpringApplication.run(Application.class, args);的类
        5.5 利用spring应用执行监听器广播上下文加载完毕事件
    6.刷新spring应用上下文
        6.1 为刷新上下文信息做准备。例如清空缓存,初始化属性信息,验证必要的属性等
        6.2 获取应用上下文的beanFactory
        6.3 对beanFactory设置相关参数
        6.4 为beanFactory添加后置处理器WebApplicationContextServletContextAwareProcessor,并忽略ServletContextAware
        6.5 调用beanFactory的后置处理器
        6.6 注册bean的后置处理器,这些后置处理器将在bean的创建过程中被调用
        6.7 初始化事件广播器(EventMulticaster),看是否有自定义的事件广播bean(applicationEventMulticaster),如果有则使用自定义的,否则就用默认的。
        6.8 初始化其他特殊的bean,比如创建serverlet容器相关的bean
        6.9 向事件广播器EventMulticaster中添加各种事件监听器
        6.10 实例化所有单例bean
        6.11 结束刷新,利用EventMulticaster广播上下文刷新完成事件
    7.执行应用runner(或命令行runner)
    8.利用spring应用执行监听器广播启动完成事件
    

 

 

你可能感兴趣的:(springboot)