今天说一下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类中,做了哪些操作;
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = 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);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
- SpringFactoriesLoader.loadFactoryNames()
- 扫描所有jar包类路径下 META‐INF/spring.factories
- 把扫描到的这些文件的内容包装成properties对象
- 从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中;
将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;
# 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.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类;
public class Cat {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private int age;
private List<String> list;
private List<Cat> listCat;
private Map<String,String> map;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
", list=" + list +
", listCat=" + listCat +
", map=" + map +
'}';
}
public List<Cat> getListCat() {
return listCat;
}
public void setListCat(List<Cat> listCat) {
this.listCat = listCat;
}
然后我们在配置文件中,给这些属性赋值,再通过这些类的对象,看能否取到我们在配置文件中给这些属性赋的值;
配置文件application.yml(springBoot默认的配置文件是application.properties&application.yml)这两个springBoot都识别,只是使用了不同的语法;我这里使用的.yml的配置;详细的yml语法可以上网查一下资料,这里就不一一赘述了,下面就是我们通过配置文件给实体类属性赋的值;
server:
port: 8081
person:
name: jerry
age: 24
list:
- tom
- jack
listCat:
- cat:
name: mary
age: 4
- cat:
name: rose
age: 30
map:
{k1: v1,k2: 12}
赋值完成后,肯定就要取值,这里我们就使用项目自动生成的测试类,来打印一下我们的生成的值;
我们通过@ConfigurationProperties注解,配置注解prefix属性是可以将配置文件中的值,成功的读取到,并注入到容器中;
接下来我们看一下SpringBoot的自动配置的如何获取到这些值得;首先我们还是找个一个自动配置类来讲,因为每一个配置类都是这样实现的,我们就随便在配置类中找一个;
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
这里我们也不找别的就找我们最熟悉的完成web项目必须的DispatcherServle这个配置,如果你对springMVC框架比较熟悉,而且用过SpringMvc框架进行过开发,应该对DispatcherServlet很熟悉的一个配置;我们看一下SpringBoot是如何替我们办了这件事;
首先找到这个类;
/**
* {@link EnableAutoConfiguration Auto-configuration} for the Spring
* {@link DispatcherServlet}. Should work for a standalone application where an embedded
* web server is already present and also for a deployable application using
* {@link SpringBootServletInitializer}.
*
* @author Phillip Webb
* @author Dave Syer
* @author Stephane Nicoll
* @author Brian Clozel
*/
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
@EnableConfigurationProperties(ServerProperties.class)
public class DispatcherServletAutoConfiguration {
/*
* The bean name for a DispatcherServlet that will be mapped to the root URL "/"
*/
public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";
/*
* The bean name for a ServletRegistrationBean for the DispatcherServlet "/"
*/
public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";
@Configuration
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {
private final WebMvcProperties webMvcProperties;
private final ServerProperties serverProperties;
public DispatcherServletConfiguration(WebMvcProperties webMvcProperties,
ServerProperties serverProperties) {
this.webMvcProperties = webMvcProperties;
this.serverProperties = serverProperties;
}
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(
this.webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(
this.webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(
this.webMvcProperties.isThrowExceptionIfNoHandlerFound());
return dispatcherServlet;
}
@Bean
@ConditionalOnBean(MultipartResolver.class)
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
@Bean
public DispatcherServletPathProvider mainDispatcherServletPathProvider() {
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即优先级):
/**
* Useful constant for the highest precedence value. //最高优先值常数
* @see java.lang.Integer#MIN_VALUE
*/
int HIGHEST_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)
public class ServerProperties {
/**
* Server HTTP port.
*/
private Integer port;
/**
* Network address to which the server should bind.
*/
private InetAddress address;
@NestedConfigurationProperty
private final ErrorProperties error = new ErrorProperties();
/**
* Whether X-Forwarded-* headers should be applied to the HttpRequest.
*/
private Boolean useForwardHeaders;
/**
* Value to use for the Server response header (if empty, no header is sent).
*/
private String serverHeader;
/**
* Maximum size, in bytes, of the HTTP message header.
*/
private int maxHttpHeaderSize = 0; // bytes
/**
* Time that connectors wait for another HTTP request before closing the connection.
* When not set, the connector's container-specific default is used. Use a value of -1
* to indicate no (that is, an infinite) timeout.
*/
private Duration connectionTimeout;
我截取了部门,可以看到这里面正是我们前面做的那个小测试,使用的方法,该如何读取到配置文件里的参数值,正是运用了@ConfigurationProperties这个注解,可以看到这个类中的属性名,就是我们配置的具体属性;
而我们DispatcherServlet配置相关就是我们前面截取的DispatcherServletAutoConfiguration自动配置类,而mvc配置在哪,我们可以看具体的方法;随便挑一个,方法实现配置,就拿web的mvc配置来讲;前面已经复制过这段代码,为了更清楚我们抽出来说;
@Configuration
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {
private final WebMvcProperties webMvcProperties;
private final ServerProperties serverProperties;
public DispatcherServletConfiguration(WebMvcProperties webMvcProperties,
ServerProperties serverProperties) {
this.webMvcProperties = webMvcProperties;
this.serverProperties = serverProperties;
}
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(
this.webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(
this.webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(
this.webMvcProperties.isThrowExceptionIfNoHandlerFound());
return dispatcherServlet;
}
@Bean
@ConditionalOnBean(MultipartResolver.class)
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
@Bean
public DispatcherServletPathProvider mainDispatcherServletPathProvider() {
return () -> DispatcherServletConfiguration.this.serverProperties.getServlet()
.getPath();
}
}
看一下这个类的配置文件@EnableConfigurationProperties(WebMvcProperties.class),WebMvcProperties.class;类中的具体属性;
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
public static class Servlet {
/**
* Load on startup priority of the dispatcher servlet.
*/
private int loadOnStartup = -1;
public int getLoadOnStartup() {
return this.loadOnStartup;
}
public void setLoadOnStartup(int loadOnStartup) {
this.loadOnStartup = loadOnStartup;
}
}
public static class View {
/**
* Spring MVC view prefix.
*/
private String prefix;
/**
* Spring MVC view suffix.
*/
private String suffix;
public String getPrefix() {
return this.prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return this.suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}
只截取了部分;看到我们之前所使用的这些配置都在这里有相应的属性;他是通过ConfigurationProperties注解中的spring.mvc来读取配置文件中的属性值,那我们就可以直接在配置文件中使用spring.mvc.属性=值 的形式来给配置文件属性赋值;
总结:
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这 些属性的值;
xxxxAutoConfigurartion:自动配置类; 给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
SpringBoot的自动配置大大简化了我们的配置过程,可以让我们专注于业务的开发。