SpringBoot启动配置原理

启动一个SpringBoot的一个应用程序;它的入口就是:下面代码中的main方法;

1

2

3

4

5

6

7

@SpringBootApplication

public class SpringbootMybatisApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(SpringbootMybatisApplication.class, args);

    }

}

从入口代码中可以看出启动流程:

 

1. 创建SpringApplication对象:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

  public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {

        // 定义启动需要的一些属性

        this.sources = new LinkedHashSet();

        this.bannerMode = Mode.CONSOLE;

        this.logStartupInfo = true;

        this.addCommandLineProperties = true;

        this.headless = true;

        this.registerShutdownHook = true;

        this.additionalProfiles = new HashSet();

        this.resourceLoader = resourceLoader;

        Assert.notNull(primarySources, "PrimarySources must not be null");

        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));

        // 判断当前是否一个web应用

        this.webApplicationType = this.deduceWebApplicationType();

        // 从类路径下找到META‐INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来

        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

        // 从类路径下找到META‐INF/spring.factories配置的所有ApplicationListener

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

        // 从多个配置类中找到有main方法的主配置类

        this.mainApplicationClass = this.deduceMainApplicationClass();

    }

 

getSpringFactoriesInstances(clazz)就是在META‐INF/spring.factories配置的所有clazz对象

 

初始化配置了6个ApplicationContextInitializer和10个ApplicationListener

在对应的jar包下找到spring.factories,可以打开看一下spring-boot和spring-boot-autoconfigure中的spring.factories的文件

其中2个ApplicationContextInitializer和1个ApplicationListener

其中4个ApplicationContextInitializer和9个ApplicationListener

基本上配置ApplicationContextInitializer和ApplicationListener都在这两个文件中了,根据需要也可以自定义添加的。

2.运行Run方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

public ConfigurableApplicationContext run(String... args) {

        StopWatch stopWatch = new StopWatch();

        stopWatch.start();

        ConfigurableApplicationContext context = null;

        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();

        this.configureHeadlessProperty();

        // 获取SpringApplicationRunListeners;从类路径下META‐INF/spring.factories

        SpringApplicationRunListeners listeners = this.getRunListeners(args);

        // 回调所有的获取SpringApplicationRunListener.starting()方法

        listeners.starting();

 

        Collection exceptionReporters;

        try {

            // 封装命令行参数

            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

            // 准备环境  创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成

            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);

            this.configureIgnoreBeanInfo(environment);

            // 打印springboot标志

            Banner printedBanner = this.printBanner(environment);

            // 创建ApplicationContext;决定创建web的ioc还是普通的ioc

            context = this.createApplicationContext();

            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, new Object[]{context});

            // 准备上下文环境;

            // 将environment保存到ioc中  context.setEnvironment(environment);

            // 调用applyInitializers()方法,回调之前保存在IOC容器中的所有的ApplicationContextInitialize的initialize方法

            // 回调SpringApplicationRunListeners中的contextPrepared方法; listeners.contextPrepared(context);

            // 回调SpringApplicationRunListeners中的contextPrepared方法   listeners.contextLoaded(context);

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

            // 刷新容器;

            // 准备刷新;清理缓存

            // 获取beanFactory  this.postProcessBeanFactory(beanFactory);

            // this.invokeBeanFactoryPostProcessors(beanFactory);

            // this.registerBeanPostProcessors(beanFactory);

            // this.initMessageSource();

            // this.initApplicationEventMulticaster();

            // this.onRefresh();

            // this.registerListeners();

            // this.finishBeanFactoryInitialization(beanFactory);

            // this.finishRefresh();

            // 扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)

            this.refreshContext(context);

            //这里什么操作也没有做

            this.afterRefresh(context, applicationArguments);

            stopWatch.stop();

            if(this.logStartupInfo) {

                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);

            }

            // 回调SpringApplicationRunListeners的started方法

            listeners.started(context);

            // 回调Runners

            // 从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调对应Runner的run方法

            // 先回调ApplicationRunne,在回调CommandLineRunner

            // 这里标准环境没有runner 注册可以回调的

            this.callRunners(context, applicationArguments);

        } catch (Throwable var10) {

            this.handleRunFailure(context, var10, exceptionReporters, listeners);

            throw new IllegalStateException(var10);

        }

 

        try {

            // 回调SpringApplicationRunListeners的running方法

            listeners.running(context);

            // 整个SpringBoot应用启动完成后返回启动的IOC容器

            return context;

        } catch (Throwable var9) {

            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);

            throw new IllegalStateException(var9);

        }

    }

在SpringBoot中的比较重要的时间回调机制有:

ApplicationContextInitializer (配置在META-INF/spring.factories)

SpringApplicationRunListener (配置在META-INF/spring.factories)

ApplicationRunner (放在IOC容器中使用@Component的方式注入就可以了)

CommandLineRunner(放在IOC容器中使用@Component的方式注入就可以了)

注册自定义的ApplicationContextInitializer :

1

2

3

4

5

6

7

public class NewApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{

 

    @Override

    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {

        System.out.println("NewApplicationContextInitializer initialize..." + configurableApplicationContext);

    }

}

注册自定义的SpringApplicationRunListener :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

public class NewSpringApplicationRunListener implements SpringApplicationRunListener{

    /**

     * 创建构造器,如果不创建会报错

     * @param springApplication

     * @param args

     */

    public NewSpringApplicationRunListener(SpringApplication springApplication, String[] args){

 

    }

    @Override

    public void starting() {

        System.out.println("1. NewSpringApplicationRunListener .... starting....");

    }

 

    @Override

    public void environmentPrepared(ConfigurableEnvironment configurableEnvironment) {

        System.out.println("2 NewSpringApplicationRunListener .... environmentPrepared....");

    }

 

    @Override

    public void contextPrepared(ConfigurableApplicationContext configurableApplicationContext) {

        System.out.println(" 3  NewSpringApplicationRunListener .... contextPrepared....");

    }

 

    @Override

    public void contextLoaded(ConfigurableApplicationContext configurableApplicationContext) {

        System.out.println("4  NewSpringApplicationRunListener .... contextLoaded....");

    }

 

    @Override

    public void started(ConfigurableApplicationContext configurableApplicationContext) {

        System.out.println(" 5  NewSpringApplicationRunListener .... started....");

    }

 

    @Override

    public void running(ConfigurableApplicationContext configurableApplicationContext) {

        System.out.println(" 6  NewSpringApplicationRunListener .... running....");

    }

 

    @Override

    public void failed(ConfigurableApplicationContext configurableApplicationContext, Throwable throwable) {

        System.out.println("NewSpringApplicationRunListener .... starting....");

    }

}

注册自定义的ApplicationRunner:

1

2

3

4

5

6

7

8

@Component

public class NewApplicationRunner implements ApplicationRunner{

 

    @Override

    public void run(ApplicationArguments applicationArguments) throws Exception {

           System.out.println("NewApplicationRunner..... run   ....");

    }

}

注册自定义的CommandLineRunner:

1

2

3

4

5

6

7

@Component

public class NewCommandLineRunner implements CommandLineRunner{

    @Override

    public void run(String... strings) throws Exception {

        System.out.println("NewCommandLineRunner....  run ........");

    }

}

对于ApplicationContextInitializer 和SpringApplicationRunListener 需要配置spring.factory文件,在resource目录下创建META-INF文件夹下面创建一个spring.factory文件将自定义的两个类注册进去;如下

在SpringBoot应用启动的时候就会按顺序调用对应类中的方法

留个问题:什么时候情况下回自定义这几种类型,希望以后学习中可以解决这个问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值