springboot源码分析01

作者: 乐乐J | 来源:发表于2019-08-02 11:58 被阅读0次

    springboot启动流程源码分析

    SpringApplication.run(MessageApplication.class, args);
    
    springboot项目启动主入口如上所示。
    /**
         * Static helper that can be used to run a {@link SpringApplication} from the
         * specified source using default settings.
         * @param primarySource the primary source to load
         * @param args the application arguments (usually passed from a Java main method)
         * @return the running {@link ApplicationContext}
         */
        public static ConfigurableApplicationContext run(Class<?> primarySource,
                String... args) {
            return run(new Class<?>[] { primarySource }, args);
        }
    

    一般来说这里是调用传入反射类实例构造方法,当着这里的反射的类实例也可以是数组形式,同时启动多个入口,启动顺序根据反射类数组的顺序决定。

    首先来粗略的说是springboot的构造部分:
    主要springboot启动的初始化方法
    /**
         * 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");
    //如果有多个主加载入口的话,会把它们转为一个linkedHashSet
            this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //设置应用的类型是servlet还是其他别的
            this.webApplicationType = deduceWebApplicationType();
    //从spring.factories中获取初始化应用需要的容器
            setInitializers((Collection) getSpringFactoriesInstances(
                    ApplicationContextInitializer.class));
    //从spring.factories中获取初始化应用需要的监听器
            setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //已main方法作为程序的主入口
            this.mainApplicationClass = deduceMainApplicationClass();
        }
    
    接下来我们实际上可以看到,构造完了之后执行了一个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) {
            return new SpringApplication(primarySources).run(args);
        }
    
    接下来才是重头戏,spring开始创建和刷新应用上下文了。
    /**
         * 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声明,主要是提供一个需要上下的实现
            ConfigurableApplicationContext context = null;
    //这里是异常处理器
            Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
            configureHeadlessProperty();
    //// 获取SpringApplicationRunListeners,内部只有一个EventPublishingRunListener
            SpringApplicationRunListeners listeners = getRunListeners(args);
            listeners.starting();
            try {
                ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                        args);
                ConfigurableEnvironment environment = prepareEnvironment(listeners,
                        applicationArguments);
    //加载环境配置文件例如 bootstrap.yml
                configureIgnoreBeanInfo(environment);
                Banner printedBanner = printBanner(environment);
    //创建应用上下文
                context = createApplicationContext();
    //获取异常处理
                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;
        }
    

    未完待续>>>

    相关文章

      网友评论

        本文标题:springboot源码分析01

        本文链接:https://www.haomeiwen.com/subject/goeabqtx.html