SpringBoot启动原理详解

試著忘記壹切 提交于 2020-01-31 22:48:42

一,本篇来说说SpringBoot的启动原理

打开启动类,调试进入可以发现SpirngBoot的启动分为两部分:
1创建SpringApplication对象
2运行Run方法

 public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }

先从创建对象讲起

 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {

        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

上面即是SpringApplication对象的创建过程
主要看最后面三行(其他代码主要是一些属性设置)


this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
---->
调试依次进入
this.getSpringFactoriesInstances()
loadFactoryNames()
loadSpringFactories()
classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
点击FACTORIES_RESOURCE_LOCATION即可有如下发现
FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
总结,通过getSpringFactoriesInstances()方法从类路径META-INF/spring.factories找到所有的ApplicationContextinitializer然后保存起来

同理第二个,同样是通过getSpringFactoriesInstances()方法从类路径下找到所有的SpringApplicationRunListeners

this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

从获取的多个配置类中,找到配置主类(且主配置类可配置多个),并返回,至此,SpringApplication对象就创建完成了

this.mainApplicationClass = this.deduceMainApplicationClass();
----->
//从获取的多个配置类中,找到包含main方法的主配置类,然后返回
 for(int var4 = 0; var4 < var3; ++var4) {
                StackTraceElement stackTraceElement = var2[var4];
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
//可配置多个主配置类
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }

第二步,运行run方法

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        //配置与AWT应用相关的配置  
        /*
          private void configureHeadlessProperty() {
        System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
    }
 */     
       this.configureHeadlessProperty();
        //获取SpringApplicationRunListeners监听器
        /*
         private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    }*/
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //回调获取所有的SpringApplicationRunListener并执行starting方法
        listeners.starting();
        //用来做异常报告分析
        Collection exceptionReporters;
        try {
        //封装命令行参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //准备环境,
        /* 
获取所有的SpringApplicationRunListener并回调environmentPrepared()方法        listeners.environmentPrepared((ConfigurableEnvironment)environment);

        */
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            //此处会在控制台打印Spring
            Banner printedBanner = this.printBanner(environment);
            //创建IOC容器
            /*
            1确定对于的IOC容器
            2利用反射创建对应的IOC容器
            protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch(this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                    break;
                case REACTIVE:
                    contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                    break;
                default:
                    contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
                }
            } catch (ClassNotFoundException var3) {
                throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
            }
        }

        return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
    }
            */
            context = this.createApplicationContext();
            //用来做异常分析报告
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            //准备上下文环境,将environment加入到IOC容器中
            /*
            1 回调之前保存的所有的ApplicationContextInitializer的initialize方法初始
            this.applyInitializers(context);
            ---->
             protected void applyInitializers(ConfigurableApplicationContext context) {
        Iterator var2 = this.getInitializers().iterator();

        while(var2.hasNext()) {
            ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
            Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
            Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
            initializer.initialize(context);
        }

####################
//2回调之前保存的所有的SpringApplicationRunListener的contextPrepared方法
    listeners.contextPrepared(context);
    ----->
     void contextPrepared(ConfigurableApplicationContext context) {
        Iterator var2 = this.listeners.iterator();

        while(var2.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
            listener.contextPrepared(context);
        }

    }
    3最后SpringApplicationRunListener监听对象执行contextLoaded方法代表容器加载完成
            */
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //刷新容器,IOC容器的初始化过程,加载所有的组件,且Web
          // 应用也是在此处加载嵌入式Tomcat容器
            this.refreshContext(context);
            //空方法
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            //从IOC容器中,获取ApplicationRunner和ComandLineRunner类
            //并回调callRunner方法
            /*
 private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
        try {
            runner.run(args);
        } catch (Exception var4) {
            throw new IllegalStateException("Failed to execute ApplicationRunner", var4);
        }
    }
    运行该事件监听器
*/
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
        //遍历SpringApplicationRunListenen,并回调方法running(),
            listeners.running(context);
            //返回IOC容器对象,SpringBoot应用启动
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!