springboot启动流程主要分为三个部分:

第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器,

第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块,

第三部分是自动化配置模块,该模块作为springboot自动配置核心,在后面的分析中会详细讨论。在下面的启动程序中我们会串联起结构中的主要功能。

每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解,以及@ImportResource注解(if need),

@SpringBootApplication包括三个注解,功能如下:

@EnableAutoConfiguration:SpringBoot根据应用所声明的依赖来对Spring框架进行自动配置

@SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境

@ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下

下面详细介绍各个启动的环节:

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

1、创建并启动计时监控类,可以看到记录当前任务的名称,默认是空字符串,然后记录当前springboot应用启动的开始时间。

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

StopWatch stopWatch = new StopWatch();

stopWatch.start();

//详细源代码

public void start() throws IllegalStateException {

    start("");

}

public void start(String taskName) throws IllegalStateException {

    if (this.currentTaskName != null) {

        throw new IllegalStateException("Can't start StopWatch: it's already running");

    }

    this.currentTaskName = taskName;

    this.startTimeNanos = System.nanoTime();

}

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

2、初始化应用上下文和异常报告集合

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

ConfigurableApplicationContext context = null;

Collection

 exceptionReporters = new ArrayList<>();

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

3、设置系统属性java.awt.headless的值:

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

/*

java.awt.headless模式是在缺少显示屏、键盘或者鼠标的系统配置

当配置了如下属性之后,应用程序可以执行如下操作:

    1、创建轻量级组件

    2、收集关于可用的字体、字体指标和字体设置的信息

    3、设置颜色来渲染准备图片

    4、创造和获取图像,为渲染准备图片

    5、使用java.awt.PrintJob,java.awt.print.*和javax.print.*类里的方法进行打印

*/

private void configureHeadlessProperty() {

        System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,

                System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));

}

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

4、创建所有spring运行监听器并发布应用启动事件

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

SpringApplicationRunListeners listeners = getRunListeners(args);

listeners.starting();

//创建spring监听器

private SpringApplicationRunListeners getRunListeners(String[] args) {

    Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };

    return new SpringApplicationRunListeners(logger,

                getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));

}

SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {

    this.log = log;

    this.listeners = new ArrayList<>(listeners);

}

//循环遍历获取监听器

void starting() {

    for (SpringApplicationRunListener listener : this.listeners) {

        listener.starting();

    }

}

//此处的监听器可以看出是事件发布监听器,主要用来发布启动事件

@Override

public void starting() {

    //这里是创建application事件‘applicationStartingEvent’

    this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));

}

//applicationStartingEvent是springboot框架最早执行的监听器,在该监听器执行started方法时,会继续发布事件,主要是基于spring的事件机制

    @Override

    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {

        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));

        //获取线程池,如果为空则同步处理。这里线程池为空,还未初始化

        Executor executor = getTaskExecutor();

        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {

            if (executor != null) {

                //异步发送事件

                executor.execute(() -> invokeListener(listener, event));

            }

            else {

                //同步发送事件

                invokeListener(listener, event);

            }

        }

    }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

5、初始化默认应用参数类

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

public DefaultApplicationArguments(String... args) {

    Assert.notNull(args, "Args must not be null");

    this.source = new Source(args);

    this.args = args;

}

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

6、根据运行监听器和应用参数来准备spring环境

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

//详细环境的准备

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,

    ApplicationArguments applicationArguments) {

    // 获取或者创建应用环境

    ConfigurableEnvironment environment = getOrCreateEnvironment();

    // 配置应用环境,配置propertySource和activeProfiles

    configureEnvironment(environment, applicationArguments.getSourceArgs());

    //listeners环境准备,广播ApplicationEnvironmentPreparedEvent

    ConfigurationPropertySources.attach(environment);

    listeners.environmentPrepared(environment);

    //将环境绑定给当前应用程序

    bindToSpringApplication(environment);

    //对当前的环境类型进行判断,如果不一致进行转换

    if (!this.isCustomEnvironment) {

        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,

                    deduceEnvironmentClass());

    }

    //配置propertySource对它自己的递归依赖

    ConfigurationPropertySources.attach(environment);

    return environment;

}

// 获取或者创建应用环境,根据应用程序的类型可以分为servlet环境、标准环境(特殊的非web环境)和响应式环境

private ConfigurableEnvironment getOrCreateEnvironment() {

    //存在则直接返回

        if (this.environment != null) {

            return this.environment;

        }

    //根据webApplicationType创建对应的Environment

        switch (this.webApplicationType) {

        case SERVLET:

            return new StandardServletEnvironment();

        case REACTIVE:

            return new StandardReactiveWebEnvironment();

        default:

            return new StandardEnvironment();

        }

    }

//配置应用环境

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {

    if (this.addConversionService) {

        ConversionService conversionService = ApplicationConversionService.getSharedInstance();

        environment.setConversionService((ConfigurableConversionService) conversionService);

    }

    //配置property sources

    configurePropertySources(environment, args);

    //配置profiles

    configureProfiles(environment, args);

}

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

7、创建banner的打印类

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

Banner printedBanner = printBanner(environment);//打印类的详细操作过程private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Banner.Mode.OFF) { return null; } ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader : new DefaultResourceLoader(getClassLoader()); SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner); if (this.bannerMode == Mode.LOG) { return bannerPrinter.print(environment, this.mainApplicationClass, logger); } return bannerPrinter.print(environment, this.mainApplicationClass, System.out); }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

8、创建应用的上下文:根据不同哦那个的应用类型初始化不同的上下文应用类

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

context = createApplicationContext();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); }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

9、准备异常报告器

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context);private 

 Collection

 getSpringFactoriesInstances(Class

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

10、准备应用上下文

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

prepareContext(context, environment, listeners, applicationArguments, printedBanner);private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //应用上下文的environment context.setEnvironment(environment); //应用上下文后处理 postProcessApplicationContext(context); //为上下文应用所有初始化器,执行容器中的applicationContextInitializer(spring.factories的实例),将所有的初始化对象放置到context对象中 applyInitializers(context); //触发所有SpringApplicationRunListener监听器的ContextPrepared事件方法。添加所有的事件监听器 listeners.contextPrepared(context); //记录启动日志 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // 注册启动参数bean,将容器指定的参数封装成bean,注入容器 ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); //设置banner if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // 加载所有资源,指的是启动器指定的参数 Set

 sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); //将bean加载到上下文中 load(context, sources.toArray(new Object[0])); //触发所有springapplicationRunListener监听器的contextLoaded事件方法, listeners.contextLoaded(context); }------------------- //这里没有做任何的处理过程,因为beanNameGenerator和resourceLoader默认为空,可以方便后续做扩展处理 protected void postProcessApplicationContext(ConfigurableApplicationContext context) { if (this.beanNameGenerator != null) { context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader != null) { if (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); } if (context instanceof DefaultResourceLoader) { ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader()); } } if (this.addConversionService) { context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance()); } }--------------------- //将启动器类加载到spring容器中,为后续的自动化配置奠定基础,之前看到的很多注解也与此相关 protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator != null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader != null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment != null) { loader.setEnvironment(this.environment); } loader.load(); }--------------------- //springboot会优先选择groovy加载方式,找不到在选择java方式 private int load(Class<?> source) { if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { // Any GroovyLoaders added in beans{} DSL can contribute beans here GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); load(loader); } if (isComponent(source)) { this.annotatedReader.register(source); return 1; } return 0; }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

11、刷新应用上下文

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

refreshContext(context);private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } }------------ public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //刷新上下文环境,初始化上下文环境,对系统的环境变量或者系统属性进行准备和校验 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //初始化beanfactory,解析xml,相当于之前的xmlBeanfactory操作 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //为上下文准备beanfactory,对beanFactory的各种功能进行填充,如@autowired,设置spel表达式解析器,设置编辑注册器,添加applicationContextAwareprocessor处理器等等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //提供子类覆盖的额外处理,即子类处理自定义的beanfactorypostProcess postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //激活各种beanfactory处理器 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //注册拦截bean创建的bean处理器,即注册beanPostProcessor registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //初始化上下文中的资源文件如国际化文件的处理 initMessageSource(); // Initialize event multicaster for this context. //初始化上下文事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //给子类扩展初始化其他bean onRefresh(); // Check for listener beans and register them. //在所有的bean中查找listener bean,然后 注册到广播器中 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //初始化剩余的非懒惰的bean,即初始化非延迟加载的bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //发完成刷新过程,通知声明周期处理器刷新过程,同时发出ContextRefreshEvent通知别人 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(); } } }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

12、应用上下文刷新后置处理

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

afterRefresh(context, applicationArguments);//当前方法的代码是空的,可以做一些自定义的后置处理操作protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

13、停止计时监控类:计时监听器停止,并统计一些任务执行信息

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

stopWatch.stop();public void stop() throws IllegalStateException { if (this.currentTaskName == null) { throw new IllegalStateException("Can't stop StopWatch: it's not running"); } long lastTime = System.nanoTime() - this.startTimeNanos; this.totalTimeNanos += lastTime; this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime); if (this.keepTaskList) { this.taskList.add(this.lastTaskInfo); } ++this.taskCount; this.currentTaskName = null; }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

14、输出日志记录执行主类名、时间信息

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

15、发布应用上下文启动完成事件:触发所有SpringapplicationRunListener监听器的started事件方法

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

listeners.started(context); void started(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.started(context); } }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

16、执行所有Runner执行器:执行所有applicationRunner和CommandLineRunner两种运行器

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

callRunners(context, applicationArguments);private void callRunners(ApplicationContext context, ApplicationArguments args) { List

 runners = new ArrayList<>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

17、发布应用上下文就绪事件:触发所有springapplicationRunnListener将挺起的running事件方法

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

listeners.running(context);void running(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.running(context); } }

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

18、返回应用上下文

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

return context;

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐