SpringBoot中文注释项目Github地址:
github.com/yuanmabiji/…
本篇接 SpringApplication目标是怎么构建的? SpringBa ! f ? : ? yoot源码(八)
1 温故而知新
温故而知新,咱们来简略回忆一下上篇的内O S | e M 0 : 9 h容,上一篇咱们剖析了SpringApplication目标的构建进程及SpringBoot自己完结的一套SPI机制,现将要害进程再浓缩3 8 P v m v + M K总结下:
-
SpringApplication
目标的E z 7 `结构进程其实便是给SpringApplication
类的6个成员变量赋值; - SpringBY O a f ^ _oot经过以下进程完结自己的SPI机制:
- 1)首要获取线程上下文类加载器;
- 2h J A F x 3)然后使用上下文类加载器从
spring.factories
配置文件中加载一切的SPI扩展完结类并放入缓存中; - 3)依据SPI接口从缓存中取出相应的SPI扩展完结类;
- 4)实例化从缓存中取出的SPI扩展完结类并回来。
2 导言
在SpringBoot发动进程中,每个不同的发动阶段会分别播送不同的内置生命周期作业,然后相应y 8 g . w y V c d的监听器会监听这些{ 5 v p 8 S [作业来 n * O f _ *履行一些初始化逻辑作业比方ConfigFileApplicationListener
会监听onApplicationEnvironmentPreparedEv@ 3 * 5 i 6 ; Jent
作业来加载配置文件applic^ R f L @ation.properties
的环境变量等。
因此本篇内容将来剖析下SpringBoot的作业监听机制的源码。
3W Q 2 R x D SpringBoC M g k # U [ Vot播送内置生命周期作业流程剖析
为了探究SpringBoot播送内置生命周期作业4 x a T [ d Z ;流程,咱们再来回忆一下SpringBoot的发动流程代码:
// SpringApplica- w h U Rtion; v A I.java
publir U W 8 x K J ^ ;c ConfigurableApplicatiQ 7 C q Z + _ x bonContext run[ 1 & V(String... args) {
StopWatch stopWatch = new StopWatch() { q p j);
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SA G * 7 KpringBootExceptC m N b W B eionReporter> exceptionReporters = new ArrayList<>2 f k w;();
configureHeadlessProperty();
// 【0】新建一个SpringAJ E fpplicationRunListeners目标用于发射SpringBoot发动进程中的生命周期作业
SpringApplicationRunListeners listeners = getRunListent : g j Qers(args);
// 【1】》》》》》发射【ApplicationStartingEvent】作业,标志, i r ^SpringApplication开端发动
listeners.staru c = ? 9 Gting();
try {
ApplicationArguments applicationArguments = new DefaultApplicat1 L g g = E / C nionArguments(
args);
// 【2】》》》》》发射【ApplicationEnvironmentPreparedEvent】作业,此刻会去加载application.properties等配置文件的环境变量,一起也有标志环境变量现已预备好的意思
ConfigurableEnvironment environment = prepareEnvironment(listeZ O Xners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicatioM R ~ z #nContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceZ @ ` W s ^ptionRepW K J Qorter.class,
new Class[] { ConfigurableApplicationContext.cl_ 9 Jass }, context);
// 【3】》》》》》发射【ApplicationContextInitializedEvent】作业,标志context容器被创立且已预备好
// 【4】》》》》》发射【ApplicationPu : (reparedEvent】作业,标志Context容器现已预备完结
prepareContext(context, environment, listeners, applicationArgumU x 3 C ; i Jents,
printedBaN F & /nner);
re{ H C p u j u P ZfreshContext(context);
afterRefresh(contex* L # q T y @ a ^t, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new Startua r pInfoLogger(2 y k 3 Dthis.mainApp~ , B s ulicatioY % 7nClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 【5】》》》》》发射【Applic; { _ationStartedEvent】作业,标志spring容器现已改写,此刻一z e d W x切的bean实例都现已加载结束
listeners.started(context);
callRunners(context, applicl N w y X *ationArguments);
}
// 【6】》》》》》发射【ApplicatD . 8ionFailedEvent】作业,标志SpringBoot发动失败
catch (T` | 9 o !hrowable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 【7】》》》》》发射【ApplicationReadyEvent】作业,标志SpringApplicatiP 4 Z gon现已正在运转即现已成功发动,能够接纳服务恳求了。P d q s @ - [ E a
lism F s :teners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporterss 0 o d $ B 6 B, null);
throw new IllegalStatT 1 1 _eException(ex);
}
return context;
}
能够看到SpringBoot在发动进程中首要会先新建一个SpringAppX # Slic: 9 9 ;ationRunListeners
目标用于发射SpringBoot发动进程中的各种生命周期作业,比方– g T C 0 J b i F发射ApplicationStartingEvent
,Ap| k Z d B U x tplicationEnvironmentPreparedEvent
和ApplicationContextInitializedEvent
等作业,然后相应的监听器会履m Z F w x . 4行一, t * 9 b : B些SpringBoot发动进程中的初始化逻辑。那么,监听这些SpringBoot的K Y } A生命周期作业的监听器们是何时被加载实例化的呢?还记得上篇文章在剖n p E 8析Sprinh 3 3gApplication
的构s , n X x F建进程吗?没错,这些履行初始化逻辑的监听器们正是在SpringApplication
的构建进程中依据A= P W k x ) D &pplicationList, 1 Aener
接口去spring.factories
配置文件中加载并实例化的。
3.1 为播送Sp7 . x J – sringBoot内置生命周期作业做前期预备
3.1.1 加载AJ a 5pplicationListener监听器完结类
咱们再来回忆下SpringApplicO @ B 1 4 T P A 1ation目标是怎么构建的? SpringBoot源码(八)一文中讲到在构建SpringApplication
目标时的setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
这句代码。
这句代码做的作业便是从spring.factories
中加载出ApplicationListener
作业监听接口的SPI扩展完结类然后添加到SpringApplication
目标的listeners
调集e ) I e中,用于后续监听SpringBootL G M 9 W I发动进程中的作业,p f 1 O E 5 % .来履行一些初始化逻辑作业。
SpringBoot发动时的具体监D @ b q e M / N听器们都完结了ApplicationListener
接口,其在spring.factories
部分配置如下:
不过在调试时,会从一切的springc ! A j q ).factories配置文件中加载监听器,终究加载了10个监听器。如下图:
3.1.Q 9 i ~2 加载SPI扩展类EventPublishingRunListener
前面讲到,在SpringBoot的发动进程中首要会先新建一个SpringApplicationRunListeners
目标用于发射SpringBoot发动I Z , j e进程中的生命周期作业,即咱们现在来看下SpringApplicationRunLT g K f ) I 2 kisteners listeners = getRunListeners(args);
这句代码:
// SpringApplication.java
private SpringApplicationRunListeners getRunListeners(String[] args) {
// 结构一个由SpringApplication.cld 7 $ Eass和String[].class组成的types
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
/ Z ] Q i 2 q/ 1) 依据SpringApplicationRunListener接口8 k W l X Q n r去sprinR | Ig.factories配置文件中加载其SPI扩展完结类
// 2) 构建一个SpringApplicationRunListeners目标并回来
return new SpringAppL | H z r L U z ylicationRunListeners(logger, getSpX } 2ringFactoriesA N % 1 T L xInstany K 9ces(
SpringApplicationRunListener.class, types, this, args));
}
咱们将要点放到getSpringFactoriesInstances(t 4 } w N J E m SpringAppl, x , PicationRunListener.class,8 * f Y ! ; types, this, args)
这句代码,getSprS [ } V ! U +ing! ` l - M ! lFactoriesInstances
这个办法咱们现已很熟悉,在上一篇剖析SpringBoot的& M – ( E S DSPI机制时现已详细剖析过这个办法。能够看到SpringBoot此刻又是依据SpringApplicatioK Y o d c ? q Y ZnRunListener
这个SPI接口去spring.factories
中加载相应的SPI扩展完结类,咱们直接去spring.factories
中看看SprF Z b k Q ^ingApplicationRunListener
有哪些SPI完结类:
由上图能够看到,SpringApplicationRunListener
只要EventPublishingRunListener
这个SPI完结类
EventPublist { l ` v ] whingRunLisC b q n e Utener
这个哥们在SpringBoot的发动进程中尤其重要,O r N由其在SpringBoot发动进程的不同Y Q T Y阶段发射不同的SpringBoot的生命周期作业,即SpringApplicatf 2 &ionRunListeners
目标没有承当播送作业的责任,而终究是托付EventPublishingRunListener
这个哥们来播送作业的。
因为e / ( 9 % , O H 5从spring.factories
中加载EventPublishingRunListener
类后还会实例化该类,那么咱们再跟进EventPH m F o 7 yublishingRunListener
的源码,看看其是怎么承当发射SpringBoo` k q @ X E A 0 3t生命周E b [期作业这一责任的?
// EventPublishingRunListener.java
public class EventPublishingRunLik l / . } Istener implements SpringApplicationRunLI ; { = 6istener, Ordered {
private final SpringApplication application;
private fi= 5 K / hnal String[] args;
/**
* 拥有一个SimpleApplicationEventMulticaster作业播送器来播送作业
*/
private fiw b * H 2 ` {nal SimpleApj x F v k i uplicationEvF o + = ? eentMulticaster initialMulticaster;
puA * Jblic EventPublishingRunListener(SpringApplip ] p : D rcation application, Stringt H w _ @ a t p[] args) {
this.apl L b r f -plication = application;
this.args = args;
// 新建一个作业播送器SimpleApplicationEventMuo v F ) * w K tlticaster目标
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 遍历在结构SpringApplication目标时从spm ? 5 - ^ . ( `ring.facS 1 6 . U /tories配置文件中获取的作业监听器
for (Applicatio1 I N c o i % X JnListener<?>, 7 L H Z 5 O listener : application.getListeners()) {
/5 J _ E q/ 将从spring.factories配置文件中获取的作业监听器们添加到作业播送器initialMulticaster目标的相关调集中
this.initialMulticaster.addAppl5 i v _ M EicationListener(listener);
}
}
@Override
public i` l unt getK G F S m K 9 DOrder() {
return 0;
}u ! o
// 》》》》》发射【ApplicationStartingEvent】作业
@Override
public void starting() {
this.? h 2 3 n 1 d QinitD Q 0ialMulticaster.multicastEvent(
new Appl* ` _ n / } Y j OicU 3 { 9ationStartingEvent(this.app| ! 3 G U _lication, t# z 5his.args));
}
// 》》》》》发射【ApplicationEnvironmentPrei = 4 5 2paredEvent】作业
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMe h ; ] Y 4 [ M 6ulticaster.multicastEvent(new ApplK j T t W d 4 y xicationEnvironmentPreparedEvent(
this.appliq C ; k v w J E Kca. d Y _ ^ ` otion, this.args, envi| % ?ronment));
}
// 》》》》》发射【ApS U 4 a | pplicationContextInitial$ 2 ^ }izedEvent】作业
@Overh c 3 3ride
public void contextPrepared(ConfigurableApplicationContext contH 6 ` & Qext) {
this.inF 1 D U v I | 9 ^itialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
this.application, this.args,P } ! ; r ? W V context));
}
// 》》》》》发射【ApplicationPreparedEvent】作业
@Override
public void contextLoaded(ConfigurableAppl6 g = 0icati] ; 1onContext co& ; ( 9 * b sntext) {
for (ApplicationListener<?> listener : this.4 C C o ^application.j ; ( c 9 n ) e FgetListeners()) {
iI 0 * 4 ` f ^ ~ -f (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationCoy 4 [ 5 q d Pntext(context);
}
context.ad] ! * sdApplicationListener(listener)3 T };
}
t) L W k w 6 + Yhis.initiak Q $ 2 5 a ~ XlMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}
// 》》》》》发射【ApplicationStartedEvent】作业V E 7 ` } ; /
@Override
public void started(ConfigurableApplicationContext context) G n u 3) {
context.publishEvent(
new ApplicationStartedEvent(this.application, this.args, context));
}
// 》》》》》发射【ApplicationW l X ( z A vReadyEvew A J + hntZ x p 3 4 ^ #】作业
@Overri1 ~ ; J ede
public+ u w voidV Z ] running(ConfigurableAX L 9pplicationContext context) {b n J
context.publishEvent(
new ApplicationReadr / = d & vyEvent(this.application, this.args, context))7 6 I;
}
// 》》》》》发射【ApplicationFailedEvent】作业
@Override
public void failed(Configurable: W B 3 $ y s R ApplicationC) , y 2 = V p ~ontext context, Throwm G X u [ ] Fable exception) {
ApplicationFailedEvent event = new ApplicationFai( Y D & 3 ~ l X /ledEvent(this.applica ! * 5 j { F J ttion,
ti . } 3his.args, context, eq C xception)* C / l;
if (context != null &@ 5 i Z D amp;& context.isH c zActive())r l , {
// Listeners have been rD ] 3 _ 9egisteR [ xred to the application context so we should
// use it at this point if we can
context.publishEvent(event);
}
else {
// An inactive context may not have a multicaster so we use our multicaster to
// calZ * f 3l all of the context's listeners instead
if (cX Y 2 s 5ontext instanceof AbstractApplicatioM E ! H r L z 8nContext) {
for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
.getApplicationListeners()) {
tw a & t 2 ~ T - Yhis.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setET c J Y 7 &rrorHandler(new LoggingED Z D P m j w o rrorHandler());
this.initialMulticaster.multicn ) ~astEvent(eve) k ^ Ont);
}
}
// ...O E , %省略非要害代码
}
能够看到EventPublishingRunListener
类完结了SpringApplicationRunListener
接口,SpringApplicationRunListener
接口界说了SpringBoot发动时发射t 6 @ r n ` x & j生命周期作业的接口办法,而EventPublisj h l Q c M * g UhingRunListener
类正是经过完结SpringApplicationRunListener
接口的starting
,environmentPrepareJ . : Y / ^d
和contextPrepa) ) i I Kred
等办法来播送Sprd P ~ j / M 6ingBoot不同的生命周期作业,咱们直接看下SpringApplicationRunA T % ? 3 k =Listener
接口源码好E 9 a了:
// SpW * ~ K 6 c P 8ringApplicationRunListener.java
public interface SpringApplicationRunListener {
void starting();
void environmentx ( , , K L % A vPrepared(ConfigurableEnvironment envM n p C W a ! zironment);
void contextPrepared(ConfigurableApplicationContext context);
vH K 9 H x , 8oid contextLoaded(Configuw V L | wrableApplicationContext context);
void started(ConfigurableApplicationContext ce * j . , 2 o Aontext);
void running(ConfigurableApplicationContext contex8 7 U p Jt);
void failed(ConfigurableApplicationContext conteR Y ] 3 oxt, Throwable exception);
}
咱们再接着剖析EventPublishingRunListener
这个类,能够看到其有一个重要的成员特点initialMulticaster
,该成Q % _员特点是SimpleApplicationEveF ) ~ : /ntS / : } z q h ]Multica( g M O } ! P q |ster
类目标,该类正是承当了播送SpringBoot发动时生命周期作业的责任,即EventPublishingRunListener
目标没有承当A g S m :播送作业的责任,而终究是托付SimpleApplicationEventMulticaster
这个哥们来播送作业的。 从EventPublishingRunL | + 3 n )istener
的源码中也能够看到在starting
,environmentPreparedy f X
和contextPrepared
等办法中也正是经过调用SimpleApp% ? a & ~ Z A ElicationEventMult^ h b h K }icaster
类目标的multicastEvent
办法来播送作业的。
考虑 Spring# 1 G ! e pBoot发动进程中发射作业时作业播送者是层层托付责任的,起初由
SpringApplicationRunListe- r W 6 o _ne- t :rs
目标承当,然后SpringApplicationRunListeners
目标将播送作业责任托付给EventPublishingRunListener
目标,终究EventPublishingRunListener
目标将播送作业的责任托付给SimpleApplicats 5 u s i IionEventMu= o W W I QlticA j i 6 O =aF & O J A Sster
目标。为什么要层层托付这么做呢? 这个值得大家考虑。
前面讲到从spring.factorh c U } 6 D Fies
中加载出EventPubla 8 6 y X P 7 | QishingRunListener
类后会实例化,而实例化必然会经过D – k ~ [EventPublishingR^ i W n AunList$ j B H 3 - _ 6ener
的结构函数来进行实例化,因此咱们接下来剖析下EventPublishingRunListener
的结构函数源码:
// EventO y b ! E k kPublishingRunLp o - Wistener.java
public EventPublishingRunListener(SpringApplicat= R 7 D ? h C : )ion application, String[] args) {
this.application = application;
this.args = args;
// 新建一个作业播送器SimpleApplicationEventMulticasti B Rer目标
this.initialMulticaster = new SimpleApplicationEventMu h o % J Ilticaster();
// 遍历在结构SpringAppl/ i e Tication目标时从spring.factories配置文件中获取的作业监听器
for (ApplicationLZ ! 7 l 9 histener<?> listener : app/ q t v 4lication.getListeners()) {
//G T h P r 将从spring.factories配置文件中获取的作业监听器们| + & n添加到作业播送器initialMulticasterN y f v + R目标的相关调集中
this.inX E 0itialMulticaster.addApplicationListener(listener);
}
}
能够看到在EventPublishingRunListener
的结构函数中有一个for
循环会遍历之前从spring.y p factories
中加载的监听器们,然后添加到调集中缓存起来,用于今后播送各种作业时直接从这个调集中取出来即可,而不必再去spring.fl & j r Tactories
中加载,进步效率。
3.2 播送SpringBoot的内置生命周期作业
从spring.factories
配置文件中加载并实例化EventPublishingRunListener
目? J = g * D –标后,那E C . $ u么在在SpringBoot的发动进程中会发射一系列SpringBoot内置的生命S = } e . o 7 O周期作业,咱们再来回忆下SpringBoot发动进程中的源码:
// SpringApq k ; 4 ` !plication.java
public ConfigurableApplicationConte: q _ A 6 y U @xt run(String... args) {
StopWatch s8 h f : & QtopWaz S 3 /tch = new StopWatch();
stopWatch - W V - *h.start();
ConfigurableApplicationContext context = null;
Cv x T * ! follection<SpringBootExceptionReporter> exceptionC 2 r 9 ^ xReporters = new Array# k m u m pList<>();
confi2 ? n ~ R v 8 @ VgureHeL Y N g *adlessProperty();
// 【0】新建一个SpringApplicationRunListeneJ d [ q ^ ~ | ~rs目标用于发射SpringBoot发动进程中的生命周期作业
SpringAppl: @ & N w ` Q wicaL $ C l wtionRunListeners listeners = getRunListeners(args);
// 【1】》》》》》发射【Applicatio5 . 0 O { j 5 hnStartingEvent】作业,标志SpringApplication开端发动
listeneA d ) # X 1rs.s1 N 2 B W w T Wtarting();
try {
Applicay i C 4tionArguments applicationArguments = new DefaultApplicationA% ? w Z Z ) a - 1rguments(
args);
// 【2】》》》》》发射【m P x S E `ApplicationEnvironmentPrepars 0 c 8 O RedEvent】作业,此刻会去加载application.properties等配置文件的环境变量,一起也有标志环境变量现已预备好的意思
ConfigurableEnvironment environment = prepareEnviron| I )ment(listeners? ; Q 3 .,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
e` K )xceptionReporters = getSpringFactoriesInstaE U ) } qncesI 2 8(
SpringBootExce0 ( a , B - ; ,ptionReporter.class,
new Class[] { Confi* 8 @ n S = *gurableApplicaa z & = , + R ItionContext.class }, contej 0 R & } mxt);
// 【3】》》》》》发射【ApplicationContextInitializedEvent】作业,标志context容器被m h ] r p 6 $创立且已预备好
// 【4】# 8 [ T t 7 ] (》》》》》发射【ApplicationPr Q } L [ 3 ` ( geparedEvent】作业,标志Context容器现已预备完结
pre; w 6 `pareContext(context, environment, listenerw 4 ) N E R 8 V Hs, applicationArguments,
printedBanner);
refreshCoX 5 S % Y ~ hntext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStartea / } - 8 F i | 7d(getApplicationLog(), stopWatch)6 $ v V;
}
/^ A % ! 8 H 6/ 【5】》》》》》发射【ApplicationStartedEvent】作业,标志spring容器现已改写,此刻一切的beanE a $ z 6 O M 5实例都现已加载结束
listeners.started(conteN e P % ! - * |xt);
callRunners(context, applicationArguments);
}
// 【6】》》》》b A + 4 2 ^》发射【Applic7 t $ K n l -ationFailedEvent】作业,标志SpringBoot发动失败
catch (Throwable ex) {
handleRunFailure(conte/ $ 2xt, ex, exc@ g 6 = x O Z =eptiF c ` j | ) monReporters, listeners);
throw new IllegalStat) ^ ) t / b 2eException(ex);
}
try {
// 【7】》》》》》发射【ApplicationReadyEvent】作业,标志SpriX e Q % y G Q p rngApplication现已正在运转即现已成功发动,能够接纳服务恳求了。
listeners.running(context);
}
catch (E M D x ! RThrb , a d 9 7 G eowable ex) {
handleRunFailure(context, exw o ! . * k ^ i 5, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
能够看到d ! 2 k ] % 7 Q S在SpringBoot的发动进程中总共会发射7种不同类型的生命周期作业,来标志SpringBoot的不同发动阶段,一起,这些生命周期作业的监听器们也会履行一些发动进程中的初始化逻辑,关于这些监听器的初始化逻辑将在下一篇内容中会剖析。以下是Spriv ~ 2 WngBoot发动进程中要发射的作业类型,其间ApplicationFailedEvent
在SpringBoot发动进程中遇到异N r g b l y常才会发射:
Applica! e w MtionStartingEvent
ApplicationEnvironmentPreparedEvent
ApplicQ y s i `ationContextInitializedEvent
ApplicationPreparedEvent
ApplicationStartedEvent
ApplicationFailedEvent
ApplicationReadyEvent
咱们以listeners.9 Z m w P }starting, # J [();
这句代码为例,看看EventPublishingRup Z DnListener
目标发射作业的源码:
// SpringApplicationRunListeners.java
publicF U c { g B d void starting() {
// 遍历listeneq g o 6 ; W b Ars调集,这儿本质取出的便是方才从spring.factories中取出的SPI完结类EventPublishingRunListener
// 而EventPublishingRu2 H # _ GnListener目标承当了Sp. b S r m kringBoot发动进程中负责播送不同的生命周期作业
for (SpringApplicati# L H J I xonRunListener listener : this.listeners) {
//k ` 5 调用EventPublishingRunListener的starting办法来播送ApplicationStartingEven , c `t作业
listener.starting();
}
}
持续跟进l^ 8 H / Eistener.6 g ] - * M Q hstarting();
的源码:
EventPublishingRunListener.java
// 》》》》》发射【Applicati9 Q e M : j S 2 conStartingEvent】作业
public vo8 ; 2 d ? V 4id starti) . 9 0 ` m 2 % ong() {
// EventPublis; G 9 ` ZhingRunListener目标将发布ApplicationStartingEvent这件作业托付给了iT O ~ n gnitE ~ x q j P wialMulticaster目标
// 调用initialMulticaster的multi2 [ c / a - n ) WcastEvent办法来发射ApplicationStartingEvent作业
thi; ` 2 r N Ms.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
能够看到,EventPub% Y Y I o W t slishingRunListener* r = J 8 k
目标将发布ApplicationStartingEvent
这件作业托付给了SimpleApplicationEventMy 2 o ~ Multid i 9 Fcaster
目标initialMulticaster
,
,而initialMulticaster
目标终究会调用其multicastEvent
办法来发射ApplicationStarl z s * 5 rtingEvent
作业。关于SimpleApplicationEventMulticaster
类怎么播送作业,笔者现已在Spring是怎么完结作业监听机制的? Spring源码(二D H r a 2 q _)这篇文章现已详细剖析,这儿不再赘述。
关于SpringBoot发动进程中发射其他生命周期作业的源码这儿不再剖析
4 SpringBoot的内置生命周期作业总结
好了,前面现已剖析了SpringBo. [ ,ot发动进程中要发射的各种生命周期作业,下面列一个表0 4 =格总结下:
5 小结
Spb _ M D Z `ringBoot发动进程中播送生命周期作业的源码剖析就到此结束了,下一篇会持续介绍监听这些生命周期作业的监听器们a y ` Y k V。咱们再回忆本篇内容总结下要害点:
SpringBoot发动进程中会发射l M 8 U ! X / f7种类型的生命周期作业,标志不同的发动阶段,然后相应的监听器会监听这些作业来履行一些初始化逻辑作业。
【源码笔记】Github源码剖析项目上线啦!!!下面是笔记的Github地址+ ` v _ _:
github.com/yuanmaq Z b ~ [ ( _ @ Hbu o @ X g 4 XiT g * r 2 Kji/…
点赞和转发是对笔者最大的激励哦| R 5 ^ C C 7 .!
大众号【源码笔记】,专心于Java后端系列框架的源码剖析。