之前看了springIOC源码,现在结合Springboot整体启动过程来看这个
重要的时间回调机制
ApplicationContextInitializer
上下文初始化器,在创建出上下文之后被执行
SpringApplicationRunListener
应用启动监听器,在各个阶段的方法,在spring启动到指定时期回调
ApplicationRunner
CommandLineRunner
用于自定义创建IOC容器完成后的操作,入参是命令行参数
自定义回调机制
ApplicationContextInitializer
、SpringApplicationRunListener
自定义需要在当前项目下的 META-INF/spring.factories
配置文件中加入自定义的实现类
关键类:
SpringApplication
:应用
SpringApplicationContext
:应用上下文
SpringApplicationRunListener
:应用运行监听器
启动步骤:
-
调用SpringApplication
的静态方法 run
方法
-
run
方法创建 SpringApplication
实例,这里用到了工厂模式,并通过 initialize
方法初始化,其中从META-INF/spring.factories
中获取 ApplicationContextInitializer
应用上下文初始化器的子类全限名,然后通过ClassLoader实例化,获取到的初始化器列表存储起来,然后通过同样的方法实例化监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @SuppressWarnings({ "unchecked", "rawtypes" }) private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
|
-
然后通过实例方法 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
| public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
|
prepareContext()
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
| private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); postProcessApplicationContext(context); applyInitializers(context); listeners.contextPrepared(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); }
context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); }
Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[sources.size()])); listeners.contextLoaded(context); }
|