springBoot启动过程 & 关键组件顺序

一、启动过程

(一)、new SpringApplication

1、判断是否为web环境

2、从spring.factories中加载: key = ApplicationContextInitializer

      注:改接口是执行refresh()方法之前调用

3、从spring.factories中加载: key = ApplicationListener

4、从当前的线程中的栈帧中找到main() 方法所在的类

(二)、run()方法

1、设置系统变量 java.awt.headless = true

2、从spring.factories 中加载 SpringApplicationRunListener   

      注:SpringApplicationRunListener  会伴随着springApplication的整个生命周期

3、利用args实例化ApplicationArguments

4、根据配置文件、JVM启动参数实例化并配置ConfigurableEnvironment

5、实例化 ConfigurableApplicationContext

6、准备 ConfigurableApplicationContext

      a、设置ConfigurableEnvironment

      b、注册bean:BeanNameGenerator

      c、执行所有的 ApplicationContextInitializer

      d、注册bean:ApplicationArguments

      e、注册bean:PrintedBanner

      f、加载所有的资源(sources)到ConfigurableApplicationContext 中

7、执行context中的refrest()方法

      注: refreshContext()--->refresh()--->AbstractApplicationContext.class  refresh()--->finishBeanFactoryInitialization()  执行非懒加载的bean--->ConfigurableListableBeanFactory.class  preInstantiateSingletons()

               实例化非懒加载的bean时,构造方法和后处理bean的前方法一起执行

8、执行ApplicationRunner、CommandlineRunner 接口中的方法

      注:两个接口中的方法是在容器启动成功后的最后一步调用

(三)、关键组件加载顺序

1、AService static===main
2、AService 构造方法===main
3、setter ===main
4、BeanPostProcessor-before 接口 ===main
5、@PostConstruct===main                                

        a、执行初始化代码,如开启资源、读取配置文件等。
6、InitializingBean 接口 ===main                        

        a、依赖于 Spring 容器的某些功能,或者需要确保所有的 Spring 特定生命周期事件已经完成,那么实现 InitializingBean 接口可能更合适。
7、BeanPostProcessor-after 接口 ===main
8、ationListener<ContextRefreshedEvent> 接口 ===main     初始化缓存数据,服务自检
9、CommandLineRunner 接口 ===main                        

        a、微服务注册

package com.study.testInit;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * @author sunxuejian
 * @date: 2024/1/28
 * @time: 3:54 PM
 * Description:
 */
@Service
public class AService implements InitializingBean, ApplicationListener<ContextRefreshedEvent>, CommandLineRunner {

    static {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("---> AService static===" + Thread.currentThread().getName());
    }

    private BService bService;

    public AService() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("---> AService 构造方法===" + Thread.currentThread().getName());
    }

    @Resource
    public void setBService(BService bService) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        this.bService = bService;
        System.out.println("---> setter ===" + Thread.currentThread().getName());
    }

    @PostConstruct
    public void init() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("---> @PostConstruct===" + Thread.currentThread().getName());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        this.bService = bService;
        System.out.println("---> InitializingBean 接口 ===" + Thread.currentThread().getName());
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        this.bService = bService;
        System.out.println("---> ApplicationListener 接口 ===" + Thread.currentThread().getName());
    }

    @Override
    public void run(String... args) throws Exception {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        this.bService = bService;
        System.out.println("---> CommandLineRunner 接口 ===" + Thread.currentThread().getName());
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值