今天说一下SpringBoot自动配置的原理,在我们之前进行的web项目开发过程中,配置文件配置繁琐,如果是多个框架集成的话可能还维护多个配置文件。这样会将我们的很多时间去花在维护配置文件,假如加一个小的功能可能就需要一个繁杂的配置。到了SpringBoot后,这种情况就大大的改善,甚至于我们如果使用了默认的配置,我们就无需再去为这些配置文件所耗费时间,专心的去考虑我们的业务功能该如何实现了。
SpringBoot是如何做到的我们之前的那么多配置项没有看到在哪里配置的,就起到了我们想要的效果呢?首先我们先创建一个web项目,通过IDEA工具,可以直接创建一个能运行的web项目,这里我就不演示了。创建完成后就是一个这样目录结构,而且还有默认的启动类。
开始正题;SpringBoot自动配置主要还是依赖启动类中的@springBootApplication,我们点开这个注解,可以看到
自动配置原理:
SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration
;
@EnableAutoConfiguration
作用:
利用EnableAutoConfigurationImportSelector
给容器中导入一些组件;我们可以在点击@EnableAutoConfiguration
看他底层是如何实现的;如图
可以看到@Import(AutoConfigurationImportSelector.class)
;一直点下去,我们会看到AutoConfigurationImportSelector
类中的getCandidateConfigurations
方法;
可以看到自动选择器类中的;List<String>configurations=SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());方法;通过SpringFactoriesLoader.loadFactoryNames()加载了什么?继续点击loadFactoryNames()往下找;
可以看到SpringFactoriesLoader类中,做了哪些操作;
privatestaticMap<String,List<String>>loadSpringFactories(@NullableClassLoaderclassLoader){MultiValueMap<String,String>result=cache.get(classLoader);if(result!=null){returnresult;}try{Enumeration<URL>urls=(classLoader!=null?classLoader.getResources(FACTORIES_RESOURCE_LOCATION):ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result=newLinkedMultiValueMap<>();while(urls.hasMoreElements()){URLurl=urls.nextElement();UrlResourceresource=newUrlResource(url);Propertiesproperties=PropertiesLoaderUtils.loadProperties(resource);for(Map.Entry<?,?>entry:properties.entrySet()){List<String>factoryClassNames=Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));result.addAll((String)entry.getKey(),factoryClassNames);}}cache.put(classLoader,result);returnresult;}catch(IOExceptionex){thrownewIllegalArgumentException("Unabletoloadfactoriesfromlocation["+FACTORIES_RESOURCE_LOCATION+"]",ex);}}
SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下META‐INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中;
将 类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration
的值加入到了容器中;
#AutoConfigureorg.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.CassandraReactiveDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\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.MongoReactiveDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\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.RedisReactiveAutoConfiguration,\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.flyway.FlywayAutoConfiguration,\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.http.HttpMessageConvertersAutoConfiguration,\org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\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.groovy.template.GroovyTemplateAutoConfiguration,\org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\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.mongo.embedded.EmbeddedMongoAutoConfiguration,\org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\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.client.RestTemplateAutoConfiguration,\org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
可以具体看一下自动配置类为我们做了哪些东西;发现我们经常用到的基本上SpringBoot都为我们考虑到了,已经将配置加入到容器中;而且这些配置类都有一个共同的特征就是以**AutoConfiguration
结尾,每一个自动配置,就是通过配置类将配置加载到容器中;如果熟悉sping配置的都知道,我们想使用某种功能的时候,也都是将具体的配置配置到spring的容器中,这里springBoot已经将我们自动配置好了;
SpringBoot的自动配置是如何配置的呢?我们是否可以根据自己的需要定制化配置呢?下面我们就看一下到底这个自动配置是如何实现的,我们自己如果写的话,该怎么来定制化的配置。
首先我们需要先熟悉两个注解:
1. @Component //将POJO对象注入到容器中,就是将每个属性值映射到容器中
2. @ConfigurationProperties //告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;prefix = "":配置文件中哪个下面的所有属性进行一一映射
我用一个小例子来演示一下这两个注解的作用,我们通过配置文件的形式来读取配置文件中的属性值(就是解释后面为什么我们在配置文件中配置完属性值后SpringBoot是如何解析到的);
首先我们见两个实体类,一个Cat类一个Person类;
publicclassCat{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}@OverridepublicStringtoString(){return"Cat{"+"name='"+name+'''+",age="+age+'}';}
@Component@ConfigurationProperties(prefix="person")publicclassPerson{privateStringname;privateintage;privateList<String>list;privateList<Cat>listCat;privateMap<String,String>map;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicList<String>getList(){returnlist;}publicvoidsetList(List<String>list){this.list=list;}publicMap<String,String>getMap(){returnmap;}publicvoidsetMap(Map<String,String>map){this.map=map;}@OverridepublicStringtoString(){return"Person{"+"name='"+name+'''+",age="+age+",list="+list+",listCat="+listCat+",map="+map+'}';}publicList<Cat>getListCat(){returnlistCat;}publicvoidsetListCat(List<Cat>listCat){this.listCat=listCat;}
然后我们在配置文件中,给这些属性赋值,再通过这些类的对象,看能否取到我们在配置文件中给这些属性赋的值;
配置文件application.yml(springBoot默认的配置文件是application.properties&application.yml)这两个springBoot都识别,只是使用了不同的语法;我这里使用的.yml的配置;详细的yml语法可以上网查一下资料,这里就不一一赘述了,下面就是我们通过配置文件给实体类属性赋的值;
server:port:8081person:name:jerryage:24list:-tom-jacklistCat:-cat:name:maryage:4-cat:name:roseage:30map:{k1:v1,k2:12}
赋值完成后,肯定就要取值,这里我们就使用项目自动生成的测试类,来打印一下我们的生成的值;
我们通过@ConfigurationProperties注解,配置注解prefix属性是可以将配置文件中的值,成功的读取到,并注入到容器中;
接下来我们看一下SpringBoot的自动配置的如何获取到这些值得;首先我们还是找个一个自动配置类来讲,因为每一个配置类都是这样实现的,我们就随便在配置类中找一个;
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
这里我们也不找别的就找我们最熟悉的完成web项目必须的DispatcherServle这个配置,如果你对springMVC框架比较熟悉,而且用过SpringMvc框架进行过开发,应该对DispatcherServlet很熟悉的一个配置;我们看一下SpringBoot是如何替我们办了这件事;
首先找到这个类;
/***{@linkEnableAutoConfigurationAuto-configuration}fortheSpring*{@linkDispatcherServlet}.Shouldworkforastandaloneapplicationwhereanembedded*webserverisalreadypresentandalsoforadeployableapplicationusing*{@linkSpringBootServletInitializer}.**@authorPhillipWebb*@authorDaveSyer*@authorStephaneNicoll*@authorBrianClozel*/@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@Configuration@ConditionalOnWebApplication(type=Type.SERVLET)@ConditionalOnClass(DispatcherServlet.class)@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)@EnableConfigurationProperties(ServerProperties.class)publicclassDispatcherServletAutoConfiguration{/**ThebeannameforaDispatcherServletthatwillbemappedtotherootURL"/"*/publicstaticfinalStringDEFAULT_DISPATCHER_SERVLET_BEAN_NAME="dispatcherServlet";/**ThebeannameforaServletRegistrationBeanfortheDispatcherServlet"/"*/publicstaticfinalStringDEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME="dispatcherServletRegistration";@Configuration@Conditional(DefaultDispatcherServletCondition.class)@ConditionalOnClass(ServletRegistration.class)@EnableConfigurationProperties(WebMvcProperties.class)protectedstaticclassDispatcherServletConfiguration{privatefinalWebMvcPropertieswebMvcProperties;privatefinalServerPropertiesserverProperties;publicDispatcherServletConfiguration(WebMvcPropertieswebMvcProperties,ServerPropertiesserverProperties){this.webMvcProperties=webMvcProperties;this.serverProperties=serverProperties;}@Bean(name=DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)publicDispatcherServletdispatcherServlet(){DispatcherServletdispatcherServlet=newDispatcherServlet();dispatcherServlet.setDispatchOptionsRequest(this.webMvcProperties.isDispatchOptionsRequest());dispatcherServlet.setDispatchTraceRequest(this.webMvcProperties.isDispatchTraceRequest());dispatcherServlet.setThrowExceptionIfNoHandlerFound(this.webMvcProperties.isThrowExceptionIfNoHandlerFound());returndispatcherServlet;}@Bean@ConditionalOnBean(MultipartResolver.class)@ConditionalOnMissingBean(name=DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)publicMultipartResolvermultipartResolver(MultipartResolverresolver){//DetectiftheuserhascreatedaMultipartResolverbutnameditincorrectlyreturnresolver;}@BeanpublicDispatcherServletPathProvidermainDispatcherServletPathProvider(){return()->DispatcherServletConfiguration.this.serverProperties.getServlet().getPath();}}
截取部分,全部截取的话占的篇幅太多;我们可以看到这个自动配置类身上有一大堆的注解;可以看一下具体都起到了什么作用:
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type=Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
@EnableConfigurationProperties(ServerProperties.class)
首先第一个@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE),如果对之前springMVC那套配置比较熟悉的话,这个配置大概能知道什么意思,Order就是我们之前配置的使用顺序,再来看下Order接口的源码如下,一目了然,值越小优先级越高,即被优先加载(precedence即优先级):
/***Usefulconstantforthehighestprecedencevalue.//最高优先值常数*@seejava.lang.Integer#MIN_VALUE*/intHIGHEST_PRECEDENCE=Integer.MIN_VALUE;
就是我们在有相同配置的情况下,谁的值越小优先级越高,
第二个注解@Configuration,这个我们应该都很清楚了表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件;
第三个注解@ConditionalOnWebApplication
Spring底层@Conditional
注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效
第四个注解:@ConditionalOnClass
当前有没有某个类,这里传入的是DispatcherServlet.class,是否有DispatcherServlet这个类,如果有这个配置文件才会生效,
第五个注解:@AutoConfigureAfter
定义这些配置类的载入顺序。
*重点 第六个注解:@EnableConfigurationProperties
启动指定类的ConfigurationProperties
功能;将配置文件中对应的值和ServerProperties绑定起来;并把ServerProperties加入到ioc容器中;
什么意思呢?我们可以据需看EnableConfigurationProperties
是如何实现的,这里的配置类的属性是ServerProperties
,就是我们配置的一些服务信息的配置;端口,地址之类;
@ConfigurationProperties(prefix="server",ignoreUnknownFields=true)publicclassServerProperties{/***ServerHTTPport.*/privateIntegerport;/***Networkaddresstowhichtheservershouldbind.*/privateInetAddressaddress;@NestedConfigurationPropertyprivatefinalErrorPropertieserror=newErrorProperties();/***WhetherX-Forwarded-*headersshouldbeappliedtotheHttpRequest.*/privateBooleanuseForwardHeaders;/***ValuetousefortheServerresponseheader(ifempty,noheaderissent).*/privateStringserverHeader;/***Maximumsize,inbytes,oftheHTTPmessageheader.*/privateintmaxHttpHeaderSize=0;//bytes/***TimethatconnectorswaitforanotherHTTPrequestbeforeclosingtheconnection.*Whennotset,theconnector'scontainer-specificdefaultisused.Useavalueof-1*toindicateno(thatis,aninfinite)timeout.*/privateDurationconnectionTimeout;
我截取了部门,可以看到这里面正是我们前面做的那个小测试,使用的方法,该如何读取到配置文件里的参数值,正是运用了@ConfigurationProperties这个注解,可以看到这个类中的属性名,就是我们配置的具体属性;
而我们DispatcherServlet配置相关就是我们前面截取的DispatcherServletAutoConfiguration自动配置类,而mvc配置在哪,我们可以看具体的方法;随便挑一个,方法实现配置,就拿web的mvc配置来讲;前面已经复制过这段代码,为了更清楚我们抽出来说;
privatestaticMap<String,List<String>>loadSpringFactories(@NullableClassLoaderclassLoader){MultiValueMap<String,String>result=cache.get(classLoader);if(result!=null){returnresult;}try{Enumeration<URL>urls=(classLoader!=null?classLoader.getResources(FACTORIES_RESOURCE_LOCATION):ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result=newLinkedMultiValueMap<>();while(urls.hasMoreElements()){URLurl=urls.nextElement();UrlResourceresource=newUrlResource(url);Propertiesproperties=PropertiesLoaderUtils.loadProperties(resource);for(Map.Entry<?,?>entry:properties.entrySet()){List<String>factoryClassNames=Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));result.addAll((String)entry.getKey(),factoryClassNames);}}cache.put(classLoader,result);returnresult;}catch(IOExceptionex){thrownewIllegalArgumentException("Unabletoloadfactoriesfromlocation["+FACTORIES_RESOURCE_LOCATION+"]",ex);}}0
看一下这个类的配置文件@EnableConfigurationProperties(WebMvcProperties.class),WebMvcProperties.class;类中的具体属性;
privatestaticMap<String,List<String>>loadSpringFactories(@NullableClassLoaderclassLoader){MultiValueMap<String,String>result=cache.get(classLoader);if(result!=null){returnresult;}try{Enumeration<URL>urls=(classLoader!=null?classLoader.getResources(FACTORIES_RESOURCE_LOCATION):ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result=newLinkedMultiValueMap<>();while(urls.hasMoreElements()){URLurl=urls.nextElement();UrlResourceresource=newUrlResource(url);Propertiesproperties=PropertiesLoaderUtils.loadProperties(resource);for(Map.Entry<?,?>entry:properties.entrySet()){List<String>factoryClassNames=Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));result.addAll((String)entry.getKey(),factoryClassNames);}}cache.put(classLoader,result);returnresult;}catch(IOExceptionex){thrownewIllegalArgumentException("Unabletoloadfactoriesfromlocation["+FACTORIES_RESOURCE_LOCATION+"]",ex);}}1
只截取了部分;看到我们之前所使用的这些配置都在这里有相应的属性;他是通过ConfigurationProperties注解中的spring.mvc来读取配置文件中的属性值,那我们就可以直接在配置文件中使用spring.mvc.属性=值 的形式来给配置文件属性赋值;
总结:
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这 些属性的值;
xxxxAutoConfigurartion:自动配置类; 给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
SpringBoot的自动配置大大简化了我们的配置过程,可以让我们专注于业务的开发。