SpringBoot 学习之自动配置讲解

       今天说一下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);
		}
	}
  1. SpringFactoriesLoader.loadFactoryNames()

  2. 扫描所有jar包类路径下 META‐INF/spring.factories

  3. 把扫描到的这些文件的内容包装成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的自动配置是如何配置的呢?我们是否可以根据自己的需要定制化配置呢?下面我们就看一下到底这个自动配置是如何实现的,我们自己如果写的话,该怎么来定制化的配置。

      首先我们需要先熟悉两个注解:

      @Component  //将POJO对象注入到容器中,就是将每个属性值映射到容器中

      @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的自动配置大大简化了我们的配置过程,可以让我们专注于业务的开发。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值