qiuyadong's Homepage

springboot启动分析


万里因循成久客,一年容易又秋风。

1、SpringApplication初始化


    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
             //设置资源类
    		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
             //推测web容器类
    		this.webApplicationType = WebApplicationType.deduceFromClasspath();
             //设置SpringFactories中的ApplicationContextInitializer
    		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
             //设置SpringFactories中的ApplicationListener
    		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
             //设置启动类
    		this.mainApplicationClass = deduceMainApplicationClass();
    	}

  • 推测web容器类

    static WebApplicationType deduceFromClasspath() {
        //存在reactive.DispatcherHandler类且没有servlet.ServletContainer类,就是REACTIVE
    		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
    				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
    			return WebApplicationType.REACTIVE;
    		}
        //存在Servlet且ConfigurableWebApplicationContext则是SERVLET,否则就是none
    		for (String className : SERVLET_INDICATOR_CLASSES) {
    			if (!ClassUtils.isPresent(className, null)) {
    				return WebApplicationType.NONE;
    			}
    		}
    		return WebApplicationType.SERVLET;
    	}

  • 设置SpringFactories中的ApplicationContextInitializer和ApplicationListener

    # Application Context Initializers
    org.springframework.context.ApplicationContextInitializer=\
    org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
    org.springframework.boot.context.ContextIdApplicationContextInitializer,\
    org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
    org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
    org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

    # Application Listeners
    org.springframework.context.ApplicationListener=\
    org.springframework.boot.ClearCachesApplicationListener,\
    org.springframework.boot.builder.ParentContextCloserApplicationListener,\
    org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
    org.springframework.boot.context.FileEncodingApplicationListener,\
    org.springframework.boot.context.config.AnsiOutputApplicationListener,\
    org.springframework.boot.context.config.ConfigFileApplicationListener,\
    org.springframework.boot.context.config.DelegatingApplicationListener,\
    org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
    org.springframework.boot.context.logging.LoggingApplicationListener,\
    org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

  • 介绍一个ConfigurationWarningsApplicationContextInitializer

  //用来报告Spring容器的一些常见的错误配置
    public class ConfigurationWarningsApplicationContextInitializer
    		implements ApplicationContextInitializer<ConfigurableApplicationContext> {

        //构建一个ConfigurationWarningsPostProcessor注册到context实例中
    public void initialize(ConfigurableApplicationContext context) {
    		context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
    	}
        //检查的check
        protected Check[] getChecks() {
    		return new Check[] { new ComponentScanPackageCheck() };
            //这里初始化一个ComponentScanPackage的检查
    	}    
        protected static final class ConfigurationWarningsPostProcessor
    			implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {
            void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry){
                //允许在Spring容器会自动检测容器的bean definition之前,进一步的注册bean definiton到容器中。特定情况下还可以通过进一步的注册bean definiton而反过来定义BeanFactoryPostProcessor接口的实例
                for (Check check : this.checks) {
    				String message = check.getWarning(registry);
    				if (StringUtils.hasLength(message)) {
    					warn(message);
    				}
    			}
            }
            void postProcessBeanFactory(ConfigurableListableBeanFactory var1){
                //允许对spring容器的bean definition进行自定义的修改,可改变容器底层管理的bean的属性值
                //Spring容器会自动检测容器的实现了BeanFactoryPostProcessor接口的Bean,如果有话将会在创建其他Bean之前首先执行该接口的代码。
                //此处为空
                ;
            }

        }
    }


  • 介绍一个ClearCachesApplicationListener

    //使用观察者模式,当上下文加载完成时通知触发该监听器
    class ClearCachesApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
        //当上下文加载完成做一些清理工作
    }

2、调用run执行


    public ConfigurableApplicationContext run(String... args) {
             //创建一个跑表
    		StopWatch stopWatch = new StopWatch();
             //启动跑表
    		stopWatch.start();

    		ConfigurableApplicationContext context = null;
    		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
            //配置Headless模式System.setProperty("java.awt.headless", "true");
    		configureHeadlessProperty();
            //获取SpringApplicationRunListener
    		SpringApplicationRunListeners listeners = getRunListeners(args);
             //# Run Listeners
             //org.springframework.boot.SpringApplicationRunListener=\
             //org.springframework.boot.context.event.EventPublishingRunListener

             //启动一个任务监听器
    		listeners.starting();
    		try {
                //获取默认参数和配置参数
    			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    			//提前准备配置环境
                ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    			configureIgnoreBeanInfo(environment);
                //根据配置的参数打印banner
    			Banner printedBanner = printBanner(environment);
                //servlet容器创建AnnotationConfigServletWebServerApplicationContext
    			context = createApplicationContext();
                //在SpringFactorie实例化SpringBootExceptionReporter的导出上下文异常信息
    			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
    					new Class[] { ConfigurableApplicationContext.class }, context);
                //上下文前置准备
    			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
                //实现上下文容器
    			refreshContext(context);
                //上下文后置处理
    			afterRefresh(context, applicationArguments);
    			stopWatch.stop();
    			if (this.logStartupInfo) {
    				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
    			}
    			listeners.started(context);
    			callRunners(context, applicationArguments);
    		}
    		catch (Throwable ex) {
    			handleRunFailure(context, ex, exceptionReporters, listeners);
    			throw new IllegalStateException(ex);
    		}

    		try {
    			listeners.running(context);
    		}
    		catch (Throwable ex) {
    			handleRunFailure(context, ex, exceptionReporters, null);
    			throw new IllegalStateException(ex);
    		}
    		return context;
    	}



Similar Posts

Comments