springboot启动源码详解

学习spring这个框架,我们总是有种感觉,会用但是不懂,“会用”是因为spring的框架利用约定大于配置的原则帮我们封装好了所有的启动配置类,这样我们使用起来的入门门槛就比较低了,只要照着官方的文档配置,一般都不会有问题,“不懂”是因为我们不知道他的底层到底是怎么实现的,有种雾里看花的感觉,一旦我们想拓展下spring的框架,就无从下手了, spring作为一个优秀的开源框架,我们很有必要去探究下他的底层实现,同时作为一名程序员,知其然也要知其所以然,要有求知欲望,这样才能站得高看的远,废话不多说,今天我们就来详细剖析下spring的启动过程(文中可能有错误的地方,希望各位看官能及时指出,非常感谢):

先看一个spring启动的例子:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
     ConfigurableApplicationContext context =  SpringApplication.run(Application.class,args);
    }
}

只要这一行启动代码,spring就为我们默认配置好了一切项目运行所必须的环境,是不是很简单,就从这里入手,看看spring到底做了什么!

public static ConfigurableApplicationContext run(Object source, String... args) {
    return run(new Object[]{source}, args);
}

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
    //调用springApplication的构造函数
    return (new SpringApplication(sources)).run(args);
}
public SpringApplication(Object... sources) {
   //创建一个新的SpringApplication对象
   initialize(sources);
}
private void initialize(Object[] sources) {
   if (sources != null && sources.length > 0) {
      this.sources.addAll(Arrays.asList(sources));
   }
   //判断是不是一个web的应用,判断的逻辑是加载 "javax.servlet.Servlet",
   //"org.springframework.web.context.ConfigurableWebApplicationContext"这两个类,如果加载成功,则是web应用
   // this.webEnvironment = true
   this.webEnvironment = deduceWebEnvironment();
   //初始化各种初始化器的实例,这些势力将会在创建好ApplicationContext后,prepare时进行调用,这里只是先对其进行实例化设值;
   //这里总共有6个Initializers,是从spring.factories配置文件里面读取到的
  //0 = {DelegatingApplicationContextInitializer@2208} 
  //1 = {ContextIdApplicationContextInitializer@2209} 
  //2 = {ConfigurationWarningsApplicationContextInitializer@2210} 
  //3 = {ServerPortInfoApplicationContextInitializer@2211} 
  //4 = {SharedMetadataReaderFactoryContextInitializer@2212} 
  //5 = {AutoConfigurationReportLoggingInitializer@2213} 


   setInitializers((Collection) getSpringFactoriesInstances(
         ApplicationContextInitializer.class));
   //设置10个listeners,实现原理同上,这里就不再赘述了,找到所有实现了ApplicationListener接口的实现类并实例化
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   //从堆栈中找到启动类的信息并加载启动类,这里就是加载Application类,到这里,初始化的工作基本完成,下面开始执行Application  //的run方法
   this.mainApplicationClass = deduceMainApplicationClass();
}
public ConfigurableApplicationContext run(String... args) {
    //new一个执行时间的监视器,记录spring启动的开始、结束时间;
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    //设置system的java.awt.headless的属性
    this.configureHeadlessProperty();
   //初始化一个SpringApplicationRunListeners对象,里面包含SpringApplicationRunListener数组,这里的数组只有一个监听器
   //对象EventPublishingRunListener,他会发布一个ApplicationStartedEvent事件,我们可以监听这个事件做一些初始化的工作,
//其初始化SpringApplicationRunListener的实现原理同上面的ApplicationListener
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting();

    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //因为是一个web应用,所以这里初始化一个StandardServletEnvironment环境对象,然后发布ApplicationEnvironmentPreparedEvent事件
        //让监听者做文件解析的工作,详情看下面的1.1节
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        //从名字就可以看出,这里就是打印banner的作用,具体的就是图案、springboot的版本号等信息
        Banner printedBanner = this.printBanner(environment);
        //创建ConfigurableApplicationContext,具体请看2.2
        context = this.createApplicationContext();

        //初始化FailureAnalyzersFailureAnalyzer 用于拦截我们感兴趣的异常,
    //并将其包装到更具可读性的 FailureAnalysis ,
    //如application-context相关的异常,默认的实现AbstractFailureAnalyzer 
    //继承于 FailureAnalyzer ,用于检查是否出现了特定的异常。如果需要
    //访问到BeanFactoryEnvironment,
    //可以实现BeanFactoryAware orEnvironmentAware接口。对于处理不了的异常,我们直接返回 null 
    //以便其他分析器可以处理。FailureAnalyzer 应该配置在 META-INF/spring.factories.才能生效,
    //如:ProjectConstraintViolationFailureAnalyzer
    //如果FailureAnalyzer实现了BeanFactoryAware接口,必须setBeanFactory设置BeanFactory
        analyzers = new FailureAnalyzers(context);
       //设置Context的属性信息,具体请看3.3
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        //刷新context,重点,具体请看4.4
        this.refreshContext(context);
        //完成刷新后的处理
        this.afterRefresh(context, applicationArguments);
         //发布一个ApplicationReadyEvent事件
        listeners.finished(context, (Throwable)null);
       //执行结束,记录执行时间
        stopWatch.stop();
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }

        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
        throw new IllegalStateException(var9);
    }
}

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    ConfigurableEnvironment environment = this.getOrCreateEnvironment();
    this.configureEnvironment(environment, applicationArguments.getSourceArgs());
    listeners.environmentPrepared(environment);
    if (this.isWebEnvironment(environment) && !this.webEnvironment) {
        environment = this.convertToStandardEnvironment(environment);
    }

    return environment;
}
1.1:new一个StandardServletEnvironment对象,并发布一个ApplicationEnvironmentPreparedEvent事件,还有做配置文件的解析的工作,监听ApplicationEnvironmentPreparedEvent事件并完成解析的工作可以参考我前面写的配置文件的解析的文章:https://blog.csdn.net/chengkui1990/article/details/79866499
private ConfigurableEnvironment prepareEnvironment(
      SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments) {
   // Create and configure the environment
   //因为是web应用,所以这里是新建了一个StandardServletEnvironment对象
   ConfigurableEnvironment environment = getOrCreateEnvironment();
  //配置环境变量的source属性和prifile属性
   configureEnvironment(environment, applicationArguments.getSourceArgs());
   //发布一个ApplicationEnvironmentPreparedEvent事件,我们也可以自己监听该实践做一些解析工作
   listeners.environmentPrepared(environment);
  //如果environment是一个webEnvironment,那么就要转换成StandardEnvironment对象
   if (isWebEnvironment(environment) && !this.webEnvironment) {
      environment = convertToStandardEnvironment(environment);
   }
   return environment;
}

2.2:创建一个ConfigurableApplicationContext对象

protected ConfigurableApplicationContext createApplicationContext() {
   Class<?> contextClass = this.applicationContextClass;
   if (contextClass == null) {
      try {
         //加载类org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext
         contextClass = Class.forName(this.webEnvironment
               ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Unable create a default ApplicationContext, "
                     + "please specify an ApplicationContextClass",
               ex);
      }
   }
   //返回一个ConfigurableApplicationContext对象,主要是通过反射:contextClass.newInstance
   return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}

3.3:设置Context的属性信息

private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
   //设置context的environment环境变量信息
   context.setEnvironment(environment);
   postProcessApplicationContext(context);
  //主要是做一些context的初始化的工作,比如设置context的id,等等,总共有6个初始化器:
  //这里的初始化器就是前面项目启动时加载的那6个Initializers,大家还有印象吗?
  //具体请看3.3.1
   applyInitializers(context);
//空的listener,什么事件都没有广播
   listeners.contextPrepared(context);
   if (this.logStartupInfo) {
     //打印启动日志,包括机器名和PID
      logStartupInfo(context.getParent() == null);
     //打印当前的profile
      logStartupProfileInfo(context);
   }

   // Add boot specific singleton beans
   //注册一个单例的beanName=springApplicationArguments的ApplicationArguments对象
   context.getBeanFactory().registerSingleton("springApplicationArguments",
         applicationArguments);
 //注册一个单例的beanName=springBootBanner的Banner对象,注册过程请看3.3.2
   if (printedBanner != null) {
      context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
   }

   // Load the sources
   Set<Object> sources = getSources();
   Assert.notEmpty(sources, "Sources must not be empty");
  //加载bean进application context,这里是加载启动类Application
   load(context, sources.toArray(new Object[sources.size()]));
  //广播一个ApplicationPreparedEvent事件
   listeners.contextLoaded(context);
}

   3.3.1:初始化器初始化context的工作:

protected void applyInitializers(ConfigurableApplicationContext context) {
  //循环迭代Initializers,逐个进行调用initialize方法,主要是填充context的属性
   for (ApplicationContextInitializer initializer : getInitializers()) {
      Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
            initializer.getClass(), ApplicationContextInitializer.class);
      Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
      initializer.initialize(context);
   }
}

3.3.2:BeanFactory注册单例bean:

@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
   //首先是调用父类的registerSingleton方法,这里的父类是DefaultSingletonBeanRegistry对象
   super.registerSingleton(beanName, singletonObject);

   if (hasBeanCreationStarted()) {
      // Cannot modify startup-time collection elements anymore (for stable iteration)
      synchronized (this.beanDefinitionMap) {
         if (!this.beanDefinitionMap.containsKey(beanName)) {
            Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames.size() + 1);
            updatedSingletons.addAll(this.manualSingletonNames);
            updatedSingletons.add(beanName);
            this.manualSingletonNames = updatedSingletons;
         }
      }
   }
   else {
      // Still in startup registration phase
       //bean不是在beanDefinitionMap里面
      if (!this.beanDefinitionMap.containsKey(beanName)) {
         //因为是手动注册的bean,所以manualSingletonNames要加入该手动注册的bean
         this.manualSingletonNames.add(beanName);
      }
   }
 //清除缓存
   clearByTypeCache();
}

DefaultSingletonBeanRegistry的registerSingleton方法:

@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
   Assert.notNull(beanName, "'beanName' must not be null");
  //先锁住singletonObjects对象,防止并发
   synchronized (this.singletonObjects) {
      Object oldObject = this.singletonObjects.get(beanName);
      if (oldObject != null) {
         throw new IllegalStateException("Could not register object [" + singletonObject +
               "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
      }
      //如果不存在,则新建单例对象
      addSingleton(beanName, singletonObject);
   }
}

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      //注册一个单例对象进入singletonObjects
      this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
      //从但例工厂里面移除这个bean
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}

4.4:刷新context:

private void refreshContext(ConfigurableApplicationContext context) {
  //刷新context
   refresh(context);
   if (this.registerShutdownHook) {
      try {
         context.registerShutdownHook();
      }
      catch (AccessControlException ex) {
         // Not allowed in some environments.
      }
   }
}
4.4.1:刷新context
protected void refresh(ApplicationContext applicationContext) {
   Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
   ((AbstractApplicationContext) applicationContext).refresh();
}
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
     //设置启动日期,close标志等于false,active标志等于true,初始化各种占位符信息
    //验证各种必须的属性是否存在,为earlyApplicationEvents集合初始化一个LinkedHashSet
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
     //设置BeanFactory的SerialiableID
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
     //设置beanFactory的beanclassloader
     //设置BeanExpressionResolver
     //设置BeanPostProcessor=ApplicationContextAwareProcessor
     //设置忽略依赖的集合和解析依赖的集合
     //注册各种单例bean对象:environment、systemProperties、systemEnvironment
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
        //注册一个ServletContextAwareProcessor
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         /**获取spring配置文件中定义的所有实现BeanFactoryPostProcessor接口的bean,然后根据优先级进行排序,之后对于每个   BeanFactoryPostProcessor,调用postProcessBeanFactory方法。
postProcessBeanFactory方法是在bean还没有初始化之前调用的,用户自己也实现该接口然后修改
bean的定义**/
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         //rehoster所有的实现了BeanPostProcessor接口的bean,这样在后面的bean
         //生成的时候拦截才能拦截并修改bean
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         //初始化一个单例的MessageSource
         initMessageSource();

         // Initialize event multicaster for this context.
         //初始化一个单例的ApplicationEventMulticaster对象
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         //初始化特殊的bean,例如embeddedServletContainer
         onRefresh();

         // Check for listener beans and register them.
         //注册所有监听器的bean,这里貌似也就是加入到一个集合中
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         //初始化所有的配置bean,这个很重要
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         完成刷新context,执行LifecycleProcessor
         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();
      }
   }
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // Initialize conversion service for this context.
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }

   // Register a default embedded value resolver if no bean post-processor
   // (such as a PropertyPlaceholderConfigurer bean) registered any before:
   // at this point, primarily for resolution in annotation attribute values.
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
         @Override
         public String resolveStringValue(String strVal) {
            return getEnvironment().resolvePlaceholders(strVal);
         }
      });
   }

   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes.
   beanFactory.freezeConfiguration();

   // Instantiate all remaining (non-lazy-init) singletons.
   //这一步很重要,这一步是初始化所有的单例的非懒加载的bean,实现还是很复杂的,具体的用户自己可以跟进去看看
   beanFactory.preInstantiateSingletons();
}
//完成刷新做的事情
protected void finishRefresh() {
   // Initialize lifecycle processor for this context.
   //初始化所有的LifecycleProcessor,没有就新建一个默认的DefaultLifecycleProcessor,并注册成一个bean
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
  //执行DefaultLifecycleProcessor的onRefresh方法
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   //广播一个ContextRefreshedEvent事件
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

写的有点乱了,未完待续吧!

猜你喜欢

转载自blog.csdn.net/chengkui1990/article/details/81297526