spring boot容器启动流程

2025-05-29 0 46

一、前言

spring cloud大行其道的当下,如果不了解基本原理那么是很纠结的(看见的都是 约定大于配置 ,但是原理呢?为什么要这么做?)。spring cloud是基于spring boot快速搭建的,今天咱们就看看spring boot容器启动流程。(本文不讲解如何快速启动spring boot,那些直接官方看即可,官网文档飞机票)

二、容器启动

spring boot一般是 指定容器启动main方法,然后以命令行方式启动jar包 ,如下图:

?

1

2

3

4

5

6
@springbootapplication

public class application {

public static void main(string[] args) {

springapplication.run(application.class, args);

}

}

这里核心关注2个东西:

1.@springbootapplication注解

2. springapplication.run()静态方法

下面我们就分别探究这两块内容。

2.1 @springbootapplication注解

源码如下:

?

1

2

3

4

5

6

7

8

9

10
@target(elementtype.type)

@retention(retentionpolicy.runtime)

@documented

@inherited

@springbootconfiguration

@enableautoconfiguration

@componentscan(excludefilters = {

@filter(type = filtertype.custom, classes = typeexcludefilter.class),

@filter(type = filtertype.custom, classes = autoconfigurationexcludefilter.class) })

public @interface springbootapplication {

核心注解:

@springbootconfiguration(实际就是个@configuration):表示这是一个javaconfig配置类,可以在这个类中自定义bean,依赖关系等。-》这个是spring-boot特有的注解,常用到。

@enableautoconfiguration:借助@import的帮助,将所有符合自动配置条件的bean定义加载到ioc容器(建议放在根包路径下,这样可以扫描子包和类)。-》这个需要详细深挖!

@componentscan:spring的自动扫描注解,可定义扫描范围,加载到ioc容器。-》这个不多说,spring的注解大家肯定眼熟

其中@enableautoconfiguration这个注解的源码:

?

1

2

3

4

5

6

7

8
@suppresswarnings("deprecation")

@target(elementtype.type)

@retention(retentionpolicy.runtime)

@documented

@inherited

@autoconfigurationpackage

@import(enableautoconfigurationimportselector.class)

public @interface enableautoconfiguration {

核心是一个enableautoconfigurationimportselector类图如下:

spring boot容器启动流程

核心方法在顶级接口 importselector 的 selectimports() ,源码如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24
@override

public string[] selectimports(annotationmetadata annotationmetadata) {

if (!isenabled(annotationmetadata)) {

return no_imports;

}

try { //1.从meta-inf/spring-autoconfigure-metadata.properties文件中载入483条配置属性(有一些有默认值),

autoconfigurationmetadata autoconfigurationmetadata = autoconfigurationmetadataloader

.loadmetadata(this.beanclassloader);

annotationattributes attributes = getattributes(annotationmetadata);//2.获取注解属性

list<string> configurations = getcandidateconfigurations(annotationmetadata,//3.获取97个自动配置类

attributes);

configurations = removeduplicates(configurations);//4.移除重复的

configurations = sort(configurations, autoconfigurationmetadata);//5.排序

set<string> exclusions = getexclusions(annotationmetadata, attributes);//6.获取需要排除的

checkexcludedclasses(configurations, exclusions);//7.校验排除类

configurations.removeall(exclusions);//8.删除所有需要排除的

configurations = filter(configurations, autoconfigurationmetadata);//9.过滤器onclasscondition(注解中配置的当存在某类才生效)

fireautoconfigurationimportevents(configurations, exclusions);//10.触发自动配置导入监听事件

return configurations.toarray(new string[configurations.size()]);

}

catch (ioexception ex) {

throw new illegalstateexception(ex);

}

}

这里注意3个核心方法:

1) loadmetadata 加载配置

其实就是用类加载器去加载: meta-inf/spring-autoconfigure-metadata.properties (spring-boot-autoconfigure-1.5.9.release-sources.jar) 文件中定义的配置,返回propertiesautoconfigurationmetadata(实现了autoconfigurationmetadata接口,封装了属性的get set方法)

2) getcandidateconfigurations 获取默认支持的自动配置类名列表

自动配置灵魂方法, springfactoriesloader.loadfactorynames 从 meta-inf/spring.factories (spring-boot-autoconfigure-1.5.9.release-sources.jar)文件中获取自动配置类key=enableautoconfiguration.class的配置。

?

1

2

3

4

5

6

7

8

9

10

11

12

13
protected list<string> getcandidateconfigurations(annotationmetadata metadata,

annotationattributes attributes) {//话说这里2个入参没啥用啊...谁来给我解释一下...

list<string> configurations = springfactoriesloader.loadfactorynames(

getspringfactoriesloaderfactoryclass(), getbeanclassloader());

assert.notempty(configurations,

"no auto configuration classes found in meta-inf/spring.factories. if you "

+ "are using a custom packaging, make sure that file is correct.");

return configurations;

}

//返回的是enableautoconfiguration类

protected class<?> getspringfactoriesloaderfactoryclass() {

return enableautoconfiguration.class;

}

实际获取了什么? spring.factories 文件如下,实际获取了 # auto configure 自动配置模块的所有类。

?

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

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123
# initializers

org.springframework.context.applicationcontextinitializer=\\

org.springframework.boot.autoconfigure.sharedmetadatareaderfactorycontextinitializer,\\

org.springframework.boot.autoconfigure.logging.autoconfigurationreportlogginginitializer

# application listeners

org.springframework.context.applicationlistener=\\

org.springframework.boot.autoconfigure.backgroundpreinitializer

# auto configuration import listeners

org.springframework.boot.autoconfigure.autoconfigurationimportlistener=\\

org.springframework.boot.autoconfigure.condition.conditionevaluationreportautoconfigurationimportlistener

# auto configuration import filters

org.springframework.boot.autoconfigure.autoconfigurationimportfilter=\\

org.springframework.boot.autoconfigure.condition.onclasscondition

# auto configure 这里就是全部的自动配置类

org.springframework.boot.autoconfigure.enableautoconfiguration=\\

org.springframework.boot.autoconfigure.admin.springapplicationadminjmxautoconfiguration,\\

org.springframework.boot.autoconfigure.aop.aopautoconfiguration,\\

org.springframework.boot.autoconfigure.amqp.rabbitautoconfiguration,\\

org.springframework.boot.autoconfigure.batch.batchautoconfiguration,\\

org.springframework.boot.autoconfigure.cache.cacheautoconfiguration,\\

org.springframework.boot.autoconfigure.cassandra.cassandraautoconfiguration,\\

org.springframework.boot.autoconfigure.cloud.cloudautoconfiguration,\\

org.springframework.boot.autoconfigure.context.configurationpropertiesautoconfiguration,\\

org.springframework.boot.autoconfigure.context.messagesourceautoconfiguration,\\

org.springframework.boot.autoconfigure.context.propertyplaceholderautoconfiguration,\\

org.springframework.boot.autoconfigure.couchbase.couchbaseautoconfiguration,\\

org.springframework.boot.autoconfigure.dao.persistenceexceptiontranslationautoconfiguration,\\

org.springframework.boot.autoconfigure.data.cassandra.cassandradataautoconfiguration,\\

org.springframework.boot.autoconfigure.data.cassandra.cassandrarepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.couchbase.couchbasedataautoconfiguration,\\

org.springframework.boot.autoconfigure.data.couchbase.couchbaserepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.elasticsearch.elasticsearchautoconfiguration,\\

org.springframework.boot.autoconfigure.data.elasticsearch.elasticsearchdataautoconfiguration,\\

org.springframework.boot.autoconfigure.data.elasticsearch.elasticsearchrepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.jpa.jparepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.ldap.ldapdataautoconfiguration,\\

org.springframework.boot.autoconfigure.data.ldap.ldaprepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.mongo.mongodataautoconfiguration,\\

org.springframework.boot.autoconfigure.data.mongo.mongorepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.neo4j.neo4jdataautoconfiguration,\\

org.springframework.boot.autoconfigure.data.neo4j.neo4jrepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.solr.solrrepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.redis.redisautoconfiguration,\\

org.springframework.boot.autoconfigure.data.redis.redisrepositoriesautoconfiguration,\\

org.springframework.boot.autoconfigure.data.rest.repositoryrestmvcautoconfiguration,\\

org.springframework.boot.autoconfigure.data.web.springdatawebautoconfiguration,\\

org.springframework.boot.autoconfigure.elasticsearch.jest.jestautoconfiguration,\\

org.springframework.boot.autoconfigure.freemarker.freemarkerautoconfiguration,\\

org.springframework.boot.autoconfigure.gson.gsonautoconfiguration,\\

org.springframework.boot.autoconfigure.h2.h2consoleautoconfiguration,\\

org.springframework.boot.autoconfigure.hateoas.hypermediaautoconfiguration,\\

org.springframework.boot.autoconfigure.hazelcast.hazelcastautoconfiguration,\\

org.springframework.boot.autoconfigure.hazelcast.hazelcastjpadependencyautoconfiguration,\\

org.springframework.boot.autoconfigure.info.projectinfoautoconfiguration,\\

org.springframework.boot.autoconfigure.integration.integrationautoconfiguration,\\

org.springframework.boot.autoconfigure.jackson.jacksonautoconfiguration,\\

org.springframework.boot.autoconfigure.jdbc.datasourceautoconfiguration,\\

org.springframework.boot.autoconfigure.jdbc.jdbctemplateautoconfiguration,\\

org.springframework.boot.autoconfigure.jdbc.jndidatasourceautoconfiguration,\\

org.springframework.boot.autoconfigure.jdbc.xadatasourceautoconfiguration,\\

org.springframework.boot.autoconfigure.jdbc.datasourcetransactionmanagerautoconfiguration,\\

org.springframework.boot.autoconfigure.jms.jmsautoconfiguration,\\

org.springframework.boot.autoconfigure.jmx.jmxautoconfiguration,\\

org.springframework.boot.autoconfigure.jms.jndiconnectionfactoryautoconfiguration,\\

org.springframework.boot.autoconfigure.jms.activemq.activemqautoconfiguration,\\

org.springframework.boot.autoconfigure.jms.artemis.artemisautoconfiguration,\\

org.springframework.boot.autoconfigure.flyway.flywayautoconfiguration,\\

org.springframework.boot.autoconfigure.groovy.template.groovytemplateautoconfiguration,\\

org.springframework.boot.autoconfigure.jersey.jerseyautoconfiguration,\\

org.springframework.boot.autoconfigure.jooq.jooqautoconfiguration,\\

org.springframework.boot.autoconfigure.kafka.kafkaautoconfiguration,\\

org.springframework.boot.autoconfigure.ldap.embedded.embeddedldapautoconfiguration,\\

org.springframework.boot.autoconfigure.ldap.ldapautoconfiguration,\\

org.springframework.boot.autoconfigure.liquibase.liquibaseautoconfiguration,\\

org.springframework.boot.autoconfigure.mail.mailsenderautoconfiguration,\\

org.springframework.boot.autoconfigure.mail.mailsendervalidatorautoconfiguration,\\

org.springframework.boot.autoconfigure.mobile.deviceresolverautoconfiguration,\\

org.springframework.boot.autoconfigure.mobile.devicedelegatingviewresolverautoconfiguration,\\

org.springframework.boot.autoconfigure.mobile.sitepreferenceautoconfiguration,\\

org.springframework.boot.autoconfigure.mongo.embedded.embeddedmongoautoconfiguration,\\

org.springframework.boot.autoconfigure.mongo.mongoautoconfiguration,\\

org.springframework.boot.autoconfigure.mustache.mustacheautoconfiguration,\\

org.springframework.boot.autoconfigure.orm.jpa.hibernatejpaautoconfiguration,\\

org.springframework.boot.autoconfigure.reactor.reactorautoconfiguration,\\

org.springframework.boot.autoconfigure.security.securityautoconfiguration,\\

org.springframework.boot.autoconfigure.security.securityfilterautoconfiguration,\\

org.springframework.boot.autoconfigure.security.fallbackwebsecurityautoconfiguration,\\

org.springframework.boot.autoconfigure.security.oauth2.oauth2autoconfiguration,\\

org.springframework.boot.autoconfigure.sendgrid.sendgridautoconfiguration,\\

org.springframework.boot.autoconfigure.session.sessionautoconfiguration,\\

org.springframework.boot.autoconfigure.social.socialwebautoconfiguration,\\

org.springframework.boot.autoconfigure.social.facebookautoconfiguration,\\

org.springframework.boot.autoconfigure.social.linkedinautoconfiguration,\\

org.springframework.boot.autoconfigure.social.twitterautoconfiguration,\\

org.springframework.boot.autoconfigure.solr.solrautoconfiguration,\\

org.springframework.boot.autoconfigure.thymeleaf.thymeleafautoconfiguration,\\

org.springframework.boot.autoconfigure.transaction.transactionautoconfiguration,\\

org.springframework.boot.autoconfigure.transaction.jta.jtaautoconfiguration,\\

org.springframework.boot.autoconfigure.validation.validationautoconfiguration,\\

org.springframework.boot.autoconfigure.web.dispatcherservletautoconfiguration,\\

org.springframework.boot.autoconfigure.web.embeddedservletcontainerautoconfiguration,\\

org.springframework.boot.autoconfigure.web.errormvcautoconfiguration,\\

org.springframework.boot.autoconfigure.web.httpencodingautoconfiguration,\\

org.springframework.boot.autoconfigure.web.httpmessageconvertersautoconfiguration,\\

org.springframework.boot.autoconfigure.web.multipartautoconfiguration,\\

org.springframework.boot.autoconfigure.web.serverpropertiesautoconfiguration,\\

org.springframework.boot.autoconfigure.web.webclientautoconfiguration,\\

org.springframework.boot.autoconfigure.web.webmvcautoconfiguration,\\

org.springframework.boot.autoconfigure.websocket.websocketautoconfiguration,\\

org.springframework.boot.autoconfigure.websocket.websocketmessagingautoconfiguration,\\

org.springframework.boot.autoconfigure.webservices.webservicesautoconfiguration

# failure analyzers

org.springframework.boot.diagnostics.failureanalyzer=\\

org.springframework.boot.autoconfigure.diagnostics.analyzer.nosuchbeandefinitionfailureanalyzer,\\

org.springframework.boot.autoconfigure.jdbc.datasourcebeancreationfailureanalyzer,\\

org.springframework.boot.autoconfigure.jdbc.hikaridriverconfigurationfailureanalyzer

# template availability providers

org.springframework.boot.autoconfigure.template.templateavailabilityprovider=\\

org.springframework.boot.autoconfigure.freemarker.freemarkertemplateavailabilityprovider,\\

org.springframework.boot.autoconfigure.mustache.mustachetemplateavailabilityprovider,\\

org.springframework.boot.autoconfigure.groovy.template.groovytemplateavailabilityprovider,\\

org.springframework.boot.autoconfigure.thymeleaf.thymeleaftemplateavailabilityprovider,\\

org.springframework.boot.autoconfigure.web.jsptemplateavailabilityprovider

3)filter过滤器 根据 onclasscondition 注解把不满足条件的过滤掉

?

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
private list<string> filter(list<string> configurations,

autoconfigurationmetadata autoconfigurationmetadata) {

long starttime = system.nanotime();

string[] candidates = configurations.toarray(new string[configurations.size()]);

boolean[] skip = new boolean[candidates.length];

boolean skipped = false;

//获取需要过滤的自动配置导入拦截器,spring.factories配置中就一个:org.springframework.boot.autoconfigure.condition.onclasscondition

for (autoconfigurationimportfilter filter : getautoconfigurationimportfilters()) {

invokeawaremethods(filter);

boolean[] match = filter.match(candidates, autoconfigurationmetadata);

for (int i = 0; i < match.length; i++) {

if (!match[i]) {

skip[i] = true;

skipped = true;

}

}

}

if (!skipped) {//多条件只要有一个不匹配->skipped = true,全部匹配-》skipped = false->直接返回

return configurations;

}

list<string> result = new arraylist<string>(candidates.length);

for (int i = 0; i < candidates.length; i++) {

if (!skip[i]) {//匹配-》不跳过-》添加进result

result.add(candidates[i]);

}

}

if (logger.istraceenabled()) {

int numberfiltered = configurations.size() - result.size();

logger.trace("filtered " + numberfiltered + " auto configuration class in "

+ timeunit.nanoseconds.tomillis(system.nanotime() - starttime)

+ " ms");

}

return new arraylist<string>(result);

}

2.2 springapplication .run()静态方法

springapplication.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
public configurableapplicationcontext run(string... args) {

stopwatch stopwatch = new stopwatch();

stopwatch.start();

configurableapplicationcontext context = null;

failureanalyzers analyzers = null;

configureheadlessproperty();

springapplicationrunlisteners listeners = getrunlisteners(args);//1.获取监听器

listeners.starting();-->启动!

try {

applicationarguments applicationarguments = new defaultapplicationarguments(

args);

configurableenvironment environment = prepareenvironment(listeners,//2.准备好环境,触发applicationenvironmentpreparedevent事件

applicationarguments);

banner printedbanner = printbanner(environment);//打印启动提示字符,默认spring的字符图

context = createapplicationcontext();//实例化一个可配置应用上下文

analyzers = new failureanalyzers(context);

preparecontext(context, environment, listeners, applicationarguments,//3.准备上下文

printedbanner);

refreshcontext(context);//4.刷新上下文

afterrefresh(context, applicationarguments);//5.刷新上下文后

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);

}

}

1. getrunlisteners 获取监听器( springapplicationrunlisteners )

实际是 springapplicationrunlistener 类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19
private springapplicationrunlisteners getrunlisteners(string[] args) {

class<?>[] types = new class<?>[] { springapplication.class, string[].class };

return new springapplicationrunlisteners(logger, getspringfactoriesinstances(

springapplicationrunlistener.class, types, this, args));

}

private <t> collection<? extends t> getspringfactoriesinstances(class<t> type) {

return getspringfactoriesinstances(type, new class<?>[] {});

}

private <t> collection<? extends t> getspringfactoriesinstances(class<t> type,

class<?>[] parametertypes, object... args) {

classloader classloader = thread.currentthread().getcontextclassloader();

// 使用set确保的字符串的唯一性

set<string> names = new linkedhashset<string>(

springfactoriesloader.loadfactorynames(type, classloader));// 1.载入工厂名称集合

list<t> instances = createspringfactoriesinstances(type, parametertypes,// 2.创建工厂实例

classloader, args, names);

annotationawareordercomparator.sort(instances);// 排序

return instances;

}

1.1 载入工厂名称(loadfactorynames)

当前类的类加载器从 meta-inf/spring.factories 文件中获取springapplicationrunlistener类的配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19
public static list<string> loadfactorynames(class<?> factoryclass, classloader classloader) {

string factoryclassname = factoryclass.getname();

try {

enumeration<url> urls = (classloader != null ? classloader.getresources(factories_resource_location) :

classloader.getsystemresources(factories_resource_location));

list<string> result = new arraylist<string>();

while (urls.hasmoreelements()) {

url url = urls.nextelement();

properties properties = propertiesloaderutils.loadproperties(new urlresource(url));

string factoryclassnames = properties.getproperty(factoryclassname);

result.addall(arrays.aslist(stringutils.commadelimitedlisttostringarray(factoryclassnames)));

}

return result;

}

catch (ioexception ex) {

throw new illegalargumentexception("unable to load [" + factoryclass.getname() +

"] factories from location [" + factories_resource_location + "]", ex);

}

}

上图,获取到工厂类名后,下面来看看meta-inf/spring.factories中定义了啥:

?

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
# propertysource loaders

org.springframework.boot.env.propertysourceloader=\\

org.springframework.boot.env.propertiespropertysourceloader,\\

org.springframework.boot.env.yamlpropertysourceloader

# run listeners 这里呢,看这里!!!!

org.springframework.boot.springapplicationrunlistener=\\

org.springframework.boot.context.event.eventpublishingrunlistener

# application context initializers

org.springframework.context.applicationcontextinitializer=\\

org.springframework.boot.context.configurationwarningsapplicationcontextinitializer,\\

org.springframework.boot.context.contextidapplicationcontextinitializer,\\

org.springframework.boot.context.config.delegatingapplicationcontextinitializer,\\

org.springframework.boot.context.embedded.serverportinfoapplicationcontextinitializer

# application listeners

org.springframework.context.applicationlistener=\\

org.springframework.boot.clearcachesapplicationlistener,\\

org.springframework.boot.builder.parentcontextcloserapplicationlistener,\\

org.springframework.boot.context.fileencodingapplicationlistener,\\

org.springframework.boot.context.config.ansioutputapplicationlistener,\\

org.springframework.boot.context.config.configfileapplicationlistener,\\

org.springframework.boot.context.config.delegatingapplicationlistener,\\

org.springframework.boot.liquibase.liquibaseservicelocatorapplicationlistener,\\

org.springframework.boot.logging.classpathloggingapplicationlistener,\\

org.springframework.boot.logging.loggingapplicationlistener

# environment post processors

org.springframework.boot.env.environmentpostprocessor=\\

org.springframework.boot.cloud.cloudfoundryvcapenvironmentpostprocessor,\\

org.springframework.boot.env.springapplicationjsonenvironmentpostprocessor

# failure analyzers

org.springframework.boot.diagnostics.failureanalyzer=\\

org.springframework.boot.diagnostics.analyzer.beancurrentlyincreationfailureanalyzer,\\

org.springframework.boot.diagnostics.analyzer.beannotofrequiredtypefailureanalyzer,\\

org.springframework.boot.diagnostics.analyzer.bindfailureanalyzer,\\

org.springframework.boot.diagnostics.analyzer.connectorstartfailureanalyzer,\\

org.springframework.boot.diagnostics.analyzer.nouniquebeandefinitionfailureanalyzer,\\

org.springframework.boot.diagnostics.analyzer.portinusefailureanalyzer,\\

org.springframework.boot.diagnostics.analyzer.validationexceptionfailureanalyzer

# failureanalysisreporters

org.springframework.boot.diagnostics.failureanalysisreporter=\\

org.springframework.boot.diagnostics.loggingfailureanalysisreporter

哇,都是些类全名称,且key都是接口,value都是实现类。我们根据key=“ org.springframework.boot.springapplicationrunlistener ”查询得到实现类value=" org.springframework.boot.context.event.eventpublishingrunlistener" 事件发布启动监听器 , 一猜也知道肯定要用” 反射 ”根据类名获取类实例,下面很快得到验证…

1.2 创建spring工厂实例(createspringfactoriesinstances)

根据第一步得到的set<string> names(springapplicationrunlistener的唯一实现类 eventpublishingrunlistener )生成" 事件发布启动监听器 " 工厂实例

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21
@suppresswarnings("unchecked")

private <t> list<t> createspringfactoriesinstances(class<t> type,

class<?>[] parametertypes, classloader classloader, object[] args,

set<string> names) {

list<t> instances = new arraylist<t>(names.size());

for (string name : names) {

try {

class<?> instanceclass = classutils.forname(name, classloader);// 利用反射获取类

assert.isassignable(type, instanceclass);

constructor<?> constructor = instanceclass

.getdeclaredconstructor(parametertypes);// 得到构造器

t instance = (t) beanutils.instantiateclass(constructor, args);// 根据构造器和参数构造实例

instances.add(instance);

}

catch (throwable ex) {

throw new illegalargumentexception(

"cannot instantiate " + type + " : " + name, ex);

}

}

return instances;

}

准备上下文

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23
private void preparecontext(configurableapplicationcontext context,

configurableenvironment environment, springapplicationrunlisteners listeners,

applicationarguments applicationarguments, banner printedbanner) {

context.setenvironment(environment);

postprocessapplicationcontext(context);//单例一个beannamegenerator,把resourceloader设置进应用上下文

applyinitializers(context);//执行初始化器

listeners.contextprepared(context);// 监听器执行上下文"已准备好"方法

if (this.logstartupinfo) {

logstartupinfo(context.getparent() == null);

logstartupprofileinfo(context);

}

// 添加spring boot特殊单例bean

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);// 监听器执行"上下文已加载"方法

}

刷新上下文

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15
private void refreshcontext(configurableapplicationcontext context) {

refresh(context);//核心类

if (this.registershutdownhook) {

try {

context.registershutdownhook();//注册关闭钩子,容器关闭时执行

}

catch (accesscontrolexception ex) {

// not allowed in some environments.

}

}

}

protected void refresh(applicationcontext applicationcontext) {

assert.isinstanceof(abstractapplicationcontext.class, applicationcontext);

((abstractapplicationcontext) applicationcontext).refresh();

}

最终执行的是abstractapplicationcontext抽象类的 refresh 方法。

?

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
public void refresh() throws beansexception, illegalstateexception {

synchronized (this.startupshutdownmonitor) {

//准备刷新的上下文环境,例如对系统属性或者环境变量进行准备及验证。

preparerefresh();

//启动子类的refreshbeanfactory方法.解析xml

configurablelistablebeanfactory beanfactory = obtainfreshbeanfactory();

//为beanfactory配置容器特性,例如类加载器、事件处理器等.

preparebeanfactory(beanfactory);

try {

//设置beanfactory的后置处理. 空方法,留给子类拓展用。

postprocessbeanfactory(beanfactory);

//调用beanfactory的后处理器, 这些后处理器是在bean定义中向容器注册的.

invokebeanfactorypostprocessors(beanfactory);

//注册bean的后处理器, 在bean创建过程中调用.

registerbeanpostprocessors(beanfactory);

//初始化上下文中的消息源,即不同语言的消息体进行国际化处理

initmessagesource();

//初始化applicationeventmulticaster bean,应用事件广播器

initapplicationeventmulticaster();

//初始化其它特殊的bean, 空方法,留给子类拓展用。

onrefresh();

//检查并向容器注册监听器bean

registerlisteners();

//实例化所有剩余的(non-lazy-init) 单例bean.

finishbeanfactoryinitialization(beanfactory);

//发布容器事件, 结束refresh过程.

finishrefresh();

}

catch (beansexception ex) {

if (logger.iswarnenabled()) {

logger.warn("exception encountered during context initialization - " +

"cancelling refresh attempt: " + ex);

}

//销毁已经创建的单例bean, 以避免资源占用.

destroybeans();

//取消refresh操作, 重置active标志.

cancelrefresh(ex);

// propagate exception to caller.

throw ex;

}

finally {

//重置spring的核心缓存

resetcommoncaches();

}

}

}

刷新完上下文后

spring boot提供的2个供用户自己拓展的接口: applicationrunner和 commandlinerunner。可以在容器启动完毕后(上下文刷新后)执行,做一些类似数据初始化的操作。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14
private void callrunners(applicationcontext context, applicationarguments args) {

list<object> runners = new arraylist<object>();

runners.addall(context.getbeansoftype(applicationrunner.class).values());//从上下文中获取applicationrunner类型的bean

runners.addall(context.getbeansoftype(commandlinerunner.class).values());//从上下文中获取commandlinerunner类型的bean

annotationawareordercomparator.sort(runners);//排序

for (object runner : new linkedhashset<object>(runners)) {

if (runner instanceof applicationrunner) {

callrunner((applicationrunner) runner, args);//执行

}

if (runner instanceof commandlinerunner) {

callrunner((commandlinerunner) runner, args);

}

}

}

两个区别在于入参不同,根据实际情况自己选择。

?

1

2

3

4

5

6
public interface commandlinerunner {

void run(string... args) throws exception;

}

public interface applicationrunner {

void run(applicationarguments args) throws exception;

}

commandlinerunner中执行参数是原始的 java启动类main方法的string[] args字符串数组参数; applicationrunner中的参数经过处理提供一些方法例如:

?

1
list<string> getoptionvalues(string name);

根据名称获取值list,java 启动命令中 –foo=bar –foo=baz,则根据foo参数名返回list ["bar", "baz"]

三、总结

spring boot容器启动流程

按照前面的分析,spring-boot容器启动流程总体可划分为2部分:

1) 执行注解 :扫描指定范围下的bean、载入自动配置类对应的bean加载到ioc容器

2)man方法中具体springappliocation.run() ,全流程贯穿springapplicationevent,有6个子类:

?

1

2

3

4

5

6
applicationfailedevent.class

applicationpreparedevent.class

applicationreadyevent.class

applicationstartedevent.class

applicationstartingevent.class

springapplicationevent.class

这里用到了很经典的 spring事件驱动模型 ,飞机票: spring事件驱动模型和观察者模式

类图如下:

spring boot容器启动流程

如上图,就是一个经典spring 事件驱动模型,包含3种角色:事件发布者、事件、监听者。对应到spring-boot中就是:

1 .eventpublishingrunlistener 这个类封装了 事件发布 ,

2. springapplicationevent 是spring-boot中定义的事件(上面说的6种事件),继承自 applicationevent (spring中定义的)

3. 监听者 spring-boot并没有实现针对上述6种事件的监听者(我没找到…), 这里用户可以自己实现监听者(上述6种事件)来注入spring boot容器启动流程,触发相应的事件。

例如:实现applicationlistener<applicationreadyevent>这个接口,在容器启动完毕时最后一步listener.finished时,如果启动没有异常,就会执行!可以做一些数据初始化之类的操作。

总结

以上所述是小编给大家介绍的spring boot容器启动的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对快网idc网站的支持!

原文链接:http://www.cnblogs.com/dennyzhangdd/p/8028950.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 spring boot容器启动流程 https://www.kuaiidc.com/112724.html

相关文章

发表评论
暂无评论