zoukankan      html  css  js  c++  java
  • SpringBoot2.3.1嵌入式Servlet启动配置原理

    从SpringBoot启动类开始看起

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

    进入run方法

        /**
         * Static helper that can be used to run a {@link SpringApplication} from the
         * specified sources using default settings and user supplied arguments.
         * @param primarySources the primary sources to load
         * @param args the application arguments (usually passed from a Java main method)
         * @return the running {@link ApplicationContext}
         */
        public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    //首先创建一个Spring应用,然后执行run方法。
    return new SpringApplication(primarySources).run(args); }

    进入new SpringApplication(primarySources)

    /**
         * Create a new {@link SpringApplication} instance. The application context will load
         * beans from the specified primary sources (see {@link SpringApplication class-level}
         * documentation for details. The instance can be customized before calling
         * {@link #run(String...)}.
         * @param resourceLoader the resource loader to use
         * @param primarySources the primary bean sources
         * @see #run(Class, String[])
         * @see #setSources(Set)
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
            this.resourceLoader = resourceLoader;
            Assert.notNull(primarySources, "PrimarySources must not be null");
            this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //判断是不是web应用
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //得到所有的META_INF下的spring.factories里面配置的
    ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
            //得到所有的META_INF下的spring.factories里面配置的ApplicationListener
             setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); 
    //得到主类
    this.mainApplicationClass = deduceMainApplicationClass(); }

    然后再进入ru/**

         * Run the Spring application, creating and refreshing a new
         * {@link ApplicationContext}.
         * @param args the application arguments (usually passed from a Java main method)
         * @return a running {@link ApplicationContext}
         */
        public ConfigurableApplicationContext run(String... args) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            ConfigurableApplicationContext context = null;
            Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
            configureHeadlessProperty();
    //得到META_INF下的spring.factoies下的SpringApplicationRunListeners SpringApplicationRunListeners listeners
    = getRunListeners(args);
    //执行每一个SpringApplicationRunListener的starting方法 listeners.starting();
    try {
    //封装命令行参数 ApplicationArguments applicationArguments
    = new DefaultApplicationArguments(args);
    //准备环境 ConfigurableEnvironment environment
    = prepareEnvironment(listeners, applicationArguments);
    /**

    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {
       // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    //这里会调用SpringApplicationRunListener的environmentPrepared方法
      listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
    environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
    deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
    }*/
    
                configureIgnoreBeanInfo(environment);
                Banner printedBanner = printBanner(environment);
    //创建ioc容器 context
    = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context);

                prepareContext(context, environment, listeners, applicationArguments, printedBanner);

                /**

    private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
    SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);
    postProcessApplicationContext(context);
    //执行ApplicationContextInitializer的initializers方法
       applyInitializers(context);
    //执行SpringApplicationRunListener的contextPrepared方法

    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
    logStartupInfo(context.getParent() == null);
    logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
    beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof DefaultListableBeanFactory) {
    ((DefaultListableBeanFactory) beanFactory)
    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.lazyInitialization) {
    context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    // Load the sources
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    //执行SpringApplicationRunListener的contextLoaded方法
       listeners.contextLoaded(context);
    }
    */
             //扫描,创建,加载所有组件的地方;(配置类,组件,自动配置),嵌入式sevlet容易在此创建   
    refreshContext(context);
    //回调ApplicationRunner和CommandLineRunner,这两个类不需要配置在spring.factoies中,直接放在ioc容器中就可以 afterRefresh(context, applicationArguments); stopWatch.stop();
    if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); }
    //执行SpringApplicaitonRunListener的started方法 listeners.started(context); callRunners(context, applicationArguments); }
    catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try {
    //执行SpringApplicationRunListener的running方法 listeners.running(context); }
    catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); }
    //返回已经启动的ioc容器
    return context; }
  • 相关阅读:
    BDB
    nginx配置文件祥解
    区分虚方法,抽象方法如此简单
    nginx+tomcat集群负载均衡(实现session复制)
    nginx配置conf
    高手博客 网址收藏
    IE6,7,8下使用Javascript记录光标选中范围(已补全)(已解决单个节点内部重复字符的问题)
    (造福中国前端界)纯前端Js完美解决各种汉字urlencode,urldecode,编码解码问题,不借助任何字库,内码表,轻松一行,兼容IE8+,chrome,firefox,safari等主流浏览器
    共享两个最近手机项目的HTML5的widget,星星评级以及标签选项卡,样式美观,iphone/android可用
    共享下改进后的combox,页面原型参考dojo的,比网上jQuery的那些combox功能强,代码更小
  • 原文地址:https://www.cnblogs.com/wxw7blog/p/13341663.html
Copyright © 2011-2022 走看看