spring boot容器启动流程
一、前言
spring cloud大行其道的当下,如果不了解基本原理那么是很纠结的(看见的都是 约定大于配置 ,但是原理呢?为什么要这么做?)。spring cloud是基于spring boot快速搭建的,今天咱们就看看spring boot容器启动流程。(本文不讲解如何快速启动spring boot,那些直接官方看即可, )
二、容器启动
spring boot一般是 指定容器启动main方法,然后以命令行方式启动jar包 ,如下图:
@springbootapplication public class application { public static void main(string[] args) { springapplication.run(application.class, args); } }
这里核心关注2个东西:
2. springapplication.run()静态方法
下面我们就分别探究这两块内容。
2.1 @springbootapplication注解
源码如下:
@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这个注解的源码:
@suppresswarnings("deprecation") @target(elementtype.type) @retention(retentionpolicy.runtime) @documented @inherited @autoconfigurationpackage @import(enableautoconfigurationimportselector.class) public @interface enableautoconfiguration {
核心是一个enableautoconfigurationimportselector类图如下:
核心方法在*接口 importselector 的 selectimports() ,源码如下:
@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的配置。
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 自动配置模块的所有类。
# 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 注解把不满足条件的过滤掉
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
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 类
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类的配置
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中定义了啥:
# 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 )生成" 事件发布启动监听器 " 工厂实例
@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; }
准备上下文
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);// 监听器执行"上下文已加载"方法 }
刷新上下文
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 方法。
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。可以在容器启动完毕后(上下文刷新后)执行,做一些类似数据初始化的操作。
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); } } }
两个区别在于入参不同,根据实际情况自己选择。
public interface commandlinerunner { void run(string... args) throws exception; } public interface applicationrunner { void run(applicationarguments args) throws exception; }
commandlinerunner中执行参数是原始的 java启动类main方法的string[] args字符串数组参数; applicationrunner中的参数经过处理提供一些方法例如:
list<string> getoptionvalues(string name);
根据名称获取值list,java 启动命令中 --foo=bar --foo=baz,则根据foo参数名返回list ["bar", "baz"]
三、总结
按照前面的分析,spring-boot容器启动流程总体可划分为2部分:
1) 执行注解 :扫描指定范围下的bean、载入自动配置类对应的bean加载到ioc容器。
2)man方法中具体springappliocation.run() ,全流程贯穿springapplicationevent,有6个子类:
applicationfailedevent.class applicationpreparedevent.class applicationreadyevent.class applicationstartedevent.class applicationstartingevent.class springapplicationevent.class
这里用到了很经典的 spring事件驱动模型 ,飞机票: spring事件驱动模型和观察者模式
类图如下:
如上图,就是一个经典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容器启动的相关知识,希望对大家有所帮助
推荐阅读
-
spring boot容器启动流程
-
Spring5源码解析1-从启动容器开始
-
基于spring-boot和docker-java实现对docker容器的动态管理和监控功能[附完整源码下载]
-
Spring Boot邮箱链接注册验证及注册流程
-
详解Spring IOC 容器启动流程分析
-
SpringBoot 源码解析 (三)----- Spring Boot 精髓:启动时初始化数据
-
把spring boot项目发布tomcat容器(包含发布到tomcat6的方法)
-
使用 Spring Boot 内嵌容器 Undertow创建服务器的方法
-
Spring Boot启动时调用自己的非web逻辑
-
选择Spring Boot项目的内嵌容器的理由