SpringBoot(二) -- SpringBoot配置
一.配置文件
SpringBoot可以使用两种类型的配置文件(文件名固定):
application.properties
application.yml
配置文件的作用就是来修改SpringBoot自动配置的默认值:SpringBoot在底层都给我们配置好了所有的配置信息
yml:YAML(YAML Ain't a Markup Language):新型配置文件.以前的配置文件大都使用到的是"xxx.xml"文件,YML以数据为中心,更适合做配置文件;
二.YML语法
1.基本语法
k:(空格)v --表示一对键值对(空格必须有);
以空格的缩进来控制层级关系: 只要是左对齐的一列数据,都是同一层级的,且属性和值都是大小写敏感的
2.值的写法
字面量: 普通的值(数字,字符串,布尔): key: value,字符串不用加引号:
""字符串:不会转义字符串中的特殊字符,特殊字符会作为本身想要表示的意思
"zhangsan \n lisi" 输出: zhangsan 换行 lisi
' '字符串: 特殊字符不会进行转义,特殊字符最终只是一个普通的字符串数据
对象,Map(属性和值)(键值对):
k: v: //在下一行来写对象的属性和值的关系,要用空格控制好缩进
k: v
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 18}
数组(List,set):
用- 值来表示数组中的一个元素
pets:
- cat
- dog
- pig
行内写法:
pets: [cat,dog,pig]
3.配置自定义类
package com.skykuqi.springboot.helloworld.entity; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import java.util.Date;
import java.util.List;
import java.util.Map; /**
* @author : S K Y
* @version :0.0.1
*/
/*将yml配置文件中配置的每一个属性的值映射到属性文件中*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth; private Map<String, Object> maps;
private List<Object> lists;
private Dog dog; public String getLastName() {
return lastName;
} public void setLastName(String lastName) {
this.lastName = lastName;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public Boolean getBoss() {
return boss;
} public void setBoss(Boolean boss) {
this.boss = boss;
} public Date getBirth() {
return birth;
} public void setBirth(Date birth) {
this.birth = birth;
} public Map<String, Object> getMaps() {
return maps;
} public void setMaps(Map<String, Object> maps) {
this.maps = maps;
} public List<Object> getLists() {
return lists;
} public void setLists(List<Object> lists) {
this.lists = lists;
} public Dog getDog() {
return dog;
} public void setDog(Dog dog) {
this.dog = dog;
} @Override
public String toString() {
return "Person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", dog=" + dog +
'}';
}
}
package com.skykuqi.springboot.helloworld.entity; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component; /**
* @author : S K Y
* @version :0.0.1
*/
@Component
@ConfigurationProperties(prefix = "dog")
public class Dog {
private String name;
private Integer age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} @Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
person:
lastName: zhangsan
age: 22
boss: true
birth: 2019/11/25
maps: {k1: 12,k2: 21}
lists:
- lisi
- zhaoliu
- wnangwu
dog:
name: 小狗
age: 3
package com.skykuqi.springboot.helloworld; import com.skykuqi.springboot.helloworld.entity.Person;
import javafx.application.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner; /**
* @author : S K Y
* @version :0.0.1
* SpringBoot单元测试
* 可以在测试期间类似编码一样进行自动注入到容器的功能,目录结构必须和原路径相同
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloWorldMainApplicationTests {
@Autowired
Person person; @Test
public void testPerson() {
System.out.println(person);
}
}
<!--配置文件的处理器,编写自定义的属性则会出现提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
4.除了使用@ConfigurationProperties注解,我们还可以使用@Value注解来完成
package com.skykuqi.springboot.helloworld.entity; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import java.util.Date;
import java.util.List;
import java.util.Map; /**
* @author : S K Y
* @version :0.0.1
*/
/*将yml配置文件中配置的每一个属性的值映射到属性文件中*/
@Component
//@ConfigurationProperties(prefix = "person")
public class Person {
@Value("${person.lastName}")
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("false")
private Boolean boss;
private Date birth; private Map<String, Object> maps;
private List<Object> lists;
private Dog dog; public String getLastName() {
return lastName;
} public void setLastName(String lastName) {
this.lastName = lastName;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public Boolean getBoss() {
return boss;
} public void setBoss(Boolean boss) {
this.boss = boss;
} public Date getBirth() {
return birth;
} public void setBirth(Date birth) {
this.birth = birth;
} public Map<String, Object> getMaps() {
return maps;
} public void setMaps(Map<String, Object> maps) {
this.maps = maps;
} public List<Object> getLists() {
return lists;
} public void setLists(List<Object> lists) {
this.lists = lists;
} public Dog getDog() {
return dog;
} public void setDog(Dog dog) {
this.dog = dog;
} @Override
public String toString() {
return "Person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", dog=" + dog +
'}';
}
}
5.@Value和@ConfigurationProperties获取值比较
功能上:@ConfigurationProperties可以批量注入配置文件中的属性,@Value必须一个一个指定
松散语法:@ConfigurationProperties支持松散绑定lastName last-name last_name 等都可以绑定到当前的属性
Spel(Spring 表达式): @Value支持Spring表达式
JSR303校验:@ConfigurationProperties支持JSR303数据校验
复杂类型封装(map):@ConfigurationProperties之处,@Value不支持
6.如果说我们只是在某个业务逻辑中只是需要获取一下配置文件中的某项值,那么我们只需要使用@Value:
@Value("${person.lastName}")
private String name; @RequestMapping("/helloWithName")
public String helloWithName() {
return "Hello " + name;
}
--如果专门配置了一个JavaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties
三.@PropertySource和@ImportResource注解的使用
@PropertySource:加载指定的配置文件,我们在使用@ConfigurationProperties注解来进行注入的时候,默认有一个要求,就是当前的配置属性需要写在默认的配置文件中(即application为文件名的配置文件,全局配置文件),如果我们把所有的配置信息都写在全局配置文件中,将会造成配置文件过大的问题,不宜阅读与维护,我们创建一个person.properties文件,而后使用@PropertySource注解完成我们的注入:
@Component
@ConfigurationProperties(prefix = "person")
@PropertySource(value = {"classpath:person.properties"})
//@Validated
public class Person {}
@ImportSource:导入Spring的配置文件,让配置文件的内容生效,在传统的开发中我们想要在Spring的配置文件中加入一个组件需要这样做:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.skykuqi.springboot.helloworld.service.HelloService"> </bean>
</beans>
package com.skykuqi.springboot.helloworld; import com.skykuqi.springboot.helloworld.entity.Person;
import javafx.application.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner; /**
* @author : S K Y
* @version :0.0.1
* SpringBoot单元测试
* 可以在测试期间类似编码一样进行自动注入到容器的功能,目录结构必须和原路径相同
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloWorldMainApplicationTests {
@Autowired
Person person; @Autowired
ApplicationContext context; @Test
public void testPerson() {
System.out.println(person);
}
@Test
public void testBeansXml(){
boolean helloService = context.containsBean("helloService");
System.out.println(helloService);
}
}
--测试我们的testBeansXml方法,发现我们自己编写的配置文件也不能自动识别,想让Spring的配置文件生效,那么我们需要将@ImportResource注解标注在我们的主配置类上:
@SpringBootApplication
@ImportResource(locations = {"classpath:beans.xml"})
public class HelloWorldMainApplication {
}
SpringBoot中推荐给容器中添加组件的方式(全注解的方式):
1.配置类:Spring配置类========>Spring配置文件:
package com.skykuqi.springboot.helloworld.config; import com.skykuqi.springboot.helloworld.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* @author : S K Y
* @version :0.0.1
*/
@Configuration //使用该注解通知SpringBoot这是一个配置类,用来替代之前的Spring配置文件
public class MyAppConfig {
/*在之前的配置文件中我们利用<bean/>标签来添加组件,在配置类中,我们使用@Bean注解来完成;
*
* 该注解将当前方法的返回值添加到Spring容器中,容器中这个组件的默认id就是方法名*/
@Bean
public HelloService helloService() {
return new HelloService();
}
}
四.配置文件占位符
我们在配置文件中可以使用Spring提供的随机数:${random.value},${random.int|long|int(10)|int[1024,65536]},此外我们还可以使用属性来匹配占位符:
person:
lastName: ${person.age}_zhangsan_${random.uuid}
age: ${random.int[2,22]}
boss: true
birth: 2019/11/25
maps: {k1: 12,k2: 21}
lists:
- lisi
- zhaoliu
- wnangwu
dog:
name: 小狗
age: 3
五.Profile(Spring多环境支撑)
在我们的日常开发中,在开发环境和正式的运行环境中,会有着一些环境上的差异,例如数据库环境,Spring可以使用@Profile注解来配置多环境:
1.我们在编写配置文件时,可以在配置文件命名时加上环境标识: application-{profile}.properties:
application-test.properties application-run.properties 默认使用的无标识后缀的默认配置文件中
a.我们可以在默认的配置文件中使用spring.profiles.active来指定当前的环境;
2.yml支持多文档块方式:
person:
lastName: ${person.age}_zhangsan_${random.uuid}
age: ${random.int[2,22]}
boss: true
birth: 2019/11/25
maps: {k1: 12,k2: 21}
lists:
- lisi
- zhaoliu
- wnangwu
dog:
name: 小狗
age: 3
# 我们可以使用---来划分文档块
spring:
profiles:
active: run
---
server:
port: 8081
spring:
profiles: test
---
server:
port: 80
spring:
profiles: run
3.此外我们还可以使用命令行方式来激活指定的配置文件:
4.我们在打包完成之后也可以在运行jar包时指定环境参数:
5.除了配置命令行参数外我们还可以配置虚拟机参数(命令行参数优先级高于JVM虚拟机参数):
六.配置文件加载位置
SpringBoot启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件,优先级高低如下:
-file:./config/
-file:./
-classpath:/config/
-classpath:/
我们也可以通过配置spring.config.location来改变默认配置
--低优先级的配置文件中的重复配置不会生效,但是在高优先级中没有定义的配置可以生效,实现互补配置
七.外部配置的加载顺序
SpringBoot如果想要进行一些配置,不止可以写在配置文件中,还可以引入外部配置,具体参照Spring官网文档说明.其中列举(按照优先级从高到低):
1.命令行参数
java -jar XXX.jar --server.port=80
2.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件;
3.jar内部的application-{profile}.properties或application.yml(带spring.profile)配置文件;
4.jar包外部的application.properties或application.yml(不带spring.profile)配置文件;
5.jar包内部的application.properties或application.yml(不带spring.profile)配置文件;
6.优先加载带profile的,再来加载不带profile,都是由jar包外向jar包内传送:
java -jar hello_world-1.0-SNAPSHOT.jar --server.port=8087 --server.context-path=/hello 多个配置用空格分开
java -jar hello_world-1.0-SNAPSHOT.jar --spring.config.location=D:\springboot_workspace\hello_world\src\main\resources\application.properties 引用外部配置文件
八.自动配置原理
配置文件能配置的属性参照Spring配置模板.
1.当SpringBoot应用启动的时候,在主配置的@SpringBootApplication中配置了@EnableAutoConfiguration
2.@EnableAutoConfiguration注解中利用@Import(EnableAutoConfigurationImportSelector.class)选择器来给SpringBoot中导入一些组件;
3.EnableAutoConfigurationImportSelector的父类AutoConfigurationImportSelector中使用public String[] selectImports(AnnotationMetadata annotationMetadata) {}方法来插入组件内容:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
4.代码第十行:List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);中获取到了当前的候选配置;在该方法中调用了SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());方法
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);
}
}
5.代码第4-5行表示的意思是在类路径下获取资源,即扫描所有jar包类路径下的public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";把扫描到的这些文件的内容包装成properties对象.而后我们在这个properties对象中(代码第9行);
6.回到protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes) {}方法,其中调用loadFactoryNames方法的参数就是EnableAutoConfiguration.class;即从properties中获取到这个类的类名对应的值,然后把他们添加在容器中.
7.总结:将类路径下的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.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
--每一个这样的XXXAutoConfiguration类都是容器中的一个组件,都加入到容器中,用他们来做自动配置.
8.每一个自动配置类进行自动配置功能,以org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration为例解释自动配置原理:
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.boot.autoconfigure.web; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.HttpEncodingProperties.Type;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.filter.OrderedCharacterEncodingFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.filter.CharacterEncodingFilter; /**
* {@link EnableAutoConfiguration Auto-configuration} for configuring the encoding to use
* in web applications.
*
* @author Stephane Nicoll
* @author Brian Clozel
* @since 1.2.0
*/
@Configuration
@EnableConfigurationProperties(HttpEncodingProperties.class)
@ConditionalOnWebApplication
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration { private final HttpEncodingProperties properties; public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
} @Bean
@ConditionalOnMissingBean(CharacterEncodingFilter.class)
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
} @Bean
public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
return new LocaleCharsetMappingsCustomizer(this.properties);
} private static class LocaleCharsetMappingsCustomizer
implements EmbeddedServletContainerCustomizer, Ordered { private final HttpEncodingProperties properties; LocaleCharsetMappingsCustomizer(HttpEncodingProperties properties) {
this.properties = properties;
} @Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (this.properties.getMapping() != null) {
container.setLocaleCharsetMappings(this.properties.getMapping());
}
} @Override
public int getOrder() {
return 0;
} } }
a.使用@Configuration注解来表示这是一个配置类
b.@EnableConfigurationProperties(HttpEncodingProperties.class) 启动指定类的@ConfigurationProperties注解
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.boot.autoconfigure.web; import java.nio.charset.Charset;
import java.util.Locale;
import java.util.Map; import org.springframework.boot.context.properties.ConfigurationProperties; /**
* Configuration properties for http encoding.
*
* @author Stephane Nicoll
* @author Brian Clozel
* @since 1.2.0
*/
@ConfigurationProperties(prefix = "spring.http.encoding")
public class HttpEncodingProperties { public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); /**
* Charset of HTTP requests and responses. Added to the "Content-Type" header if not
* set explicitly.
*/
private Charset charset = DEFAULT_CHARSET; /**
* Force the encoding to the configured charset on HTTP requests and responses.
*/
private Boolean force; /**
* Force the encoding to the configured charset on HTTP requests. Defaults to true
* when "force" has not been specified.
*/
private Boolean forceRequest; /**
* Force the encoding to the configured charset on HTTP responses.
*/
private Boolean forceResponse; /**
* Locale to Encoding mapping.
*/
private Map<Locale, Charset> mapping; public Charset getCharset() {
return this.charset;
} public void setCharset(Charset charset) {
this.charset = charset;
} public boolean isForce() {
return Boolean.TRUE.equals(this.force);
} public void setForce(boolean force) {
this.force = force;
} public boolean isForceRequest() {
return Boolean.TRUE.equals(this.forceRequest);
} public void setForceRequest(boolean forceRequest) {
this.forceRequest = forceRequest;
} public boolean isForceResponse() {
return Boolean.TRUE.equals(this.forceResponse);
} public void setForceResponse(boolean forceResponse) {
this.forceResponse = forceResponse;
} public Map<Locale, Charset> getMapping() {
return this.mapping;
} public void setMapping(Map<Locale, Charset> mapping) {
this.mapping = mapping;
} boolean shouldForce(Type type) {
Boolean force = (type == Type.REQUEST ? this.forceRequest : this.forceResponse);
if (force == null) {
force = this.force;
}
if (force == null) {
force = (type == Type.REQUEST);
}
return force;
} enum Type { REQUEST, RESPONSE } }
c. @ConfigurationProperties(prefix = "spring.http.encoding")注解则表示从配置文件中获取指定的值和bean的属性进行绑定.
9.所有在配置文件中能配置的属性都在properties中封装着,因此我们想知道配置文件可以配置什么就可以参照某个功能对应的这个属性类,上述类所表示的就是解决HTTP的编码自动配置功能,将配置文件中对应的值和HttpEncodingProperties绑定起来.
10.回到HttpEncodingAutoConfiguration类的文件中@ConditionalOnWebApplication在Spring底层中,@Conditional注解,根据不同的条件,如果能满足指定的条件,整个配置类才会生效.而@ConditionalOnWebApplication表示的是判断当前应用是否是Web应用.如果是,则当前的配置类生效.
11.@ConditionalOnClass(CharacterEncodingFilter.class) 用来判断当前项目有没有这个类,该类时SpringMVC中进行乱码解决的过滤器(通常配置在web.xml中让其起作用);
12.@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)判断配置文件中是否存在某个配置,如果不存在matchIfMissing 表示判断也是成立的.即即使我们配置文件中不配置spring.http.encoding.enabled=true,默认也是生效的.
13.总结:自动配置类就是根据当前不同的条件判断,而后决定这个配置类是否生效,如果一旦生效,在该类中使用@Bean注解将zhCharacterEncodingFilter这个类添加到了Spring容器中,这个组件的某些值需要从properties中获取,而HttpEncodingProperties配置类的属性已经和springBoot的配置文件连接了,而其默认的encoding编码就是public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");此外我们还可以配置如下属性:
a.force:即启用强制编码
14.我们能配置的属性都是来源于这个功能的Properties类.一旦这个配置类生效,那么这个类就会 给容器中添加各种组件,这些组件的属性是从对应的properties文件中获取的.
15.精髓:因为SpringBoot启动会加载大量的自动配置类,所以我们可以看我们需要的功能有没有SpringBoot已经写好的自动配置类,然后我们可以看我们的自动配置类中有哪些自动配置的属性.只要我们要使用的组件已经存在,我们就不需要再来配置了.给容器的自动配置类添加组件时,会从properties类之中获取某些属性,我们可以在配置文件中指定这些属性的值;
16.在SpringBoot之中有很多的xxxAutoConfiguration自动配置类来给容器中添加这个组件,也有与之对应的xxxProperties类来封装这个配置文件中相关的属性.
九.@Conditional注解详解
在HttpEncodingAutoConfiguration 类中还存在一个@ConditionalOnMissingBean(CharacterEncodingFilter.class)注解表示的是当缺失这个bean的时候那么进行自动配置.
1.@Conditional注解:当指定的条件成立,那么配置类中的所有内容才生效,但是SpringBoot将这些注解扩展了很多:
@ConditionalOnJava:系统的Java版本是否符合要求;
@ConditionalOnBean:容器中存在指定的Bean
@ConditionalOnMissingBean:容器中不存在指定Bean
@ConditionalOnExpression:是否满足一个指定的SpEL表达式
@ConditionalOnClass:系统中有指定的类
@ConditionalMissingClass:系统中不存在当前的类
@ConditionalOnSingleCandidate:容器中只有一个指定的bean,或者这个bean是首选bean
@ConditionalOnProperty:系统中指定的属性是否为指定的值
@ConditionalOnResources:类路径下是否存在指定的资源文件
@ConditionalOnWebApplication:当前是web环境
@ConditionalNotWebApplicaiton:当前不是web环境
@ConditionalOnJndi:Jndi存在指定项
2.自动配置类在一定的条件下才能生效:
@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
}
3.可以发现只有当我们存在Aspect的jar时,当前的配合类才能生效,因此我们现在的任务就是如何知道哪些自动配置类生效了
我们可以在配置文件中使用debug=true来开启SpringBoot的Debug模式,在控制台中我们就可以看到当前启动了哪一项自动配置类.
SpringBoot(二) -- SpringBoot配置的更多相关文章
- springboot(二).springboot整合logback用于日志输出
springboot整合logback用于日志输出 我们项目的基本框架已经完成,http请求已经可以访问,现在给我们的框架添加日志记录的功能并能将每天的记录记录到文件中去 在这里,我们使用logbac ...
- SpringBoot(二) SpringBoot核心配置文件application.yml/properties
我们都知道在Spring中有着application.xml文件对Spring进行相关配置,通过web.xml中的contextConfigLocation指定application.xml文件所在位 ...
- SpringBoot(二): SpringBoot属性配置文件 SpringBoot多环境配置文件 SpringBoot自定义配置文件
1.属性配置文件 一共分为两种,一种是键值对的properties属性配置文件,一种是yaml格式的配置文件 properties配置: 2.多环境配置文件 当我们的项目中有多套配置文件 比如开发的配 ...
- SpringBoot学习<二>——SpringBoot的默认配置文件application和多环境配置
一.SpringBoot的默认文件appliction 上一篇文章已经说明,springboot启动会内嵌tomcat,端口也是默认的8080,如果我们想要改变端口如果做呢? 在springboot项 ...
- SpringBoot系列(十二)过滤器配置详解
SpringBoot(十二)过滤器详解 往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件 ...
- 【Nacos】Springboot整合Nacos配置中心(二) 多环境配置
本篇随笔接上一篇文章:Springboot整合Nacos配置中心(一),主要记录Nacos多环境的配置的方法 Nacos多环境的配置 方法一: 1.在项目中的bootstrap.yaml文件中配置激活 ...
- springboot深入学习(二)-----profile配置、运行原理、web开发
一.profile配置 通常企业级应用都会区分开发环境.测试环境以及生产环境等等.spring提供了全局profile配置的方式,使得在不同环境下使用不同的applicaiton.properties ...
- SpringBoot(二) 主程序详解和配置文件如何配置
SpringBoot主程序详解 /** * @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用 */ @SpringBootApplication ...
- 【SpringBoot】SpringBoot配置与单元测试(二)
SpringBoot项目创建参考[SpringBoot]SpringBoot快速入门(一) 本文介绍SpringBoot项目的POM文件.配置与单元测试 POM文件 1.SpringBoot的pom文 ...
随机推荐
- Linux 安装 Composer
Linux 安装 Composer 入门 练习环境: 虚拟机:Oracle VM VirtualBox. 系统:CentOS 7. 安装方式一: 参考网址:https://learnku.com/c ...
- php理解递归
递归有一段时间很让人难已理解,突然发现一个很好的办法来理解,现在跟大家分享一下: <?php function fact(n){ if( n == 1){ return 1; } retrun ...
- jvm slot复用
如果当前字节码PC计数器的值已经超出了某个变量的作用域,那这个变量对应的Slot就可以交给其他变量使用. 字节码PC计数器就是程序计数器,程序计数器记录当前线程所执行的字节码的偏移地址.如果这个值超出 ...
- python frozenset集合(17)
在前一篇文章中我们对 python set集合 做了详细的讲解,而本文讲解的 frozenset集合 其实和set集合类似!区别在于frozenset集合不能修改/添加/删除,其他功能和set集合一样 ...
- luogu 4004 Hello world! 分块 + 并查集 + 乱搞
其实呢,我也不理解这道题咋做,等以后有时间再研究研究 #include <bits/stdc++.h> #define ll long long #define maxn 100002 u ...
- Comet OJ - Contest #6 D. 另一道树题 并查集 + 思维 + 计数
Code: #include <cstdio> #include <algorithm> #include <cstring> #include <vecto ...
- [CF535D]Tavas and Malekas 题解
题意简述 有一个空着的长度为\(n\)的字符串\(ans\),再给出一个长度为\(m\)的序列\(a\),现要在序列中每个元素\(a_i\)的位置开始都规定必须为一个给定的字符串\(s\).问字符串\ ...
- SQL读取表中不重复字段
通关关键字 distinct 将AlbumName字段中所以不重复的内容读出来.
- 170907-关于JavaWeb的题
1. 答案是B.D Servlet 通过调用 init () 方法进行初始化. Servlet 调用 service() 方法来处理客户端的请求. Servlet 通过调用 destroy() 方法终 ...
- paper about spring
一.解析用户原始信息的json文件 #!/usr/bin/python # -*- coding=utf-8 -*- import os import sys import json def main ...