Spring Boot基础(五)SpringBoot启动流程

 

SpringBoot从主类的main方法中的run方法进入,跳转到Application类中的ConfigurableApplicationContext方法,new了一个SpringApplication对象,并且执行了它的run方法

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

 

当new一个SprngApplication对象时,调用了SpringApplication的构造方法:

复制代码
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        
        this.resourceLoader = resourceLoader;
        //判断是否有主类
        Assert.notNull(primarySources, "PrimarySources must not be null");
        //参数放入一个set
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //判断是否为web环境
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
        //从配置文件中获取Initializers和Listeners两种监听器的名字
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }
复制代码

 

执行完构造后,对象初始化完毕,监听器已获取,开始真正执行run方法

复制代码
public ConfigurableApplicationContext run(String... args) {
        //计时
        long startTime = System.nanoTime();
        DefaultBootstrapContext bootstrapContext = createBootstrapContext();
        ConfigurableApplicationContext context = null;
        configureHeadlessProperty();
        //获取获取所有的RunListener(包括自己定义的)
        SpringApplicationRunListeners listeners = getRunListeners(args);
        //调用所有Listeners的Startting方法
        listeners.starting(bootstrapContext, this.mainApplicationClass);
        try {
            //准备启动,封装参数对象
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //准备环境,
            ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
            //开始创建context(即IoC容器)
            context = createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            //传入listeners,Initializer被初始化。Ioc已创建完毕,未加载Bean
            prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            //刷新context,在配置中寻找并创建Bean
            refreshContext(context);
            afterRefresh(context, applicationArguments);
            //计时停止
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
            }
            //执行后,项目启动成功
            listeners.started(context, timeTakenToStartup);
            //回调Runner,即ApplicationRunne 和CommandLineRunner被调用
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, listeners);
            throw new IllegalStateException(ex);
        }
        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, null);
            throw new IllegalStateException(ex);
        }
        //返回IoC容器
        return context;
    }
复制代码

 

Startting方法,旧版是用for-each方法实现:

    void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
        doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
                (step) -> {
                    if (mainApplicationClass != null) {
                        step.tag("mainApplicationClass", mainApplicationClass.getName());
                    }
                });
    }

 

posted @   我永远喜欢石原里美  阅读(94)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示