1.配置文件
SpringBoot使用一个全局的配置文件,配置文件名是固定的:
- application.properties
- application.yml
配置文件的作用是修改SpringBoot自动配置的默认值,这些值SpringBoot都在底层帮我们设置好。
那什么是yml文件?
YAML( YAML Ain't Markup Language) :
- YAML A Markup Language 是一个标记语言
- YAML isn't Markup Language 不是一个标记语言。
以前的配置文件,大多是使用xxx.xml文件。YAML是以数据为中心,比json,xml文件。配置例子如下:
server:
prot:8081
2.YAML语法
2.1 基本语法
k:(空格)v:表示一对键值对(空格必须有)。以空格的缩进来控制层级关系;只要左对齐的一列数据,都是同一层级的。
属性和值的大小写敏感
2.2 值的写法
2.2.1 字面量:普通的值(数字,字符串,布尔)
字符串默认不用加上单引号或者双引号。
"":双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思。
'':单引号,会转义特殊字符,特殊字符最终只是一个普通的字符串数据。
2.2.2 对象,Map(属性和值)(键值对)
k: v :在下一行来写对象的属性和值的关系。注意缩进。
对象还是k: v的方式
friends:
lastname:zhangsan
age:20
比较专业的写法:
friend:{lastname:张三,age:18}
2.2.3 数组(List,Set)
用-值表述数组中的一个元素
pets:
-cat
-dog
-pig
比较专业的写法
pets:[cat,dog,pig]
三.配置文件值注入
3.1 例子
配置文件:
person:
lastName: hello
age: 18
boss: false
maps: {k1: v1,k2: 12}
lists:
-lisi
-zhaoliu
JavaBean:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/*
将配置文件中的配置的每一个属性的值,映射到这个组件中
@ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
prefix="person" :配置文件中的哪个的所有属性进行一一映射
只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties的功能
*/
@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;
}
导入配置文件处理器,配置文件进行绑定就会有提示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
测试类(在test包下):一定要注意这个@Test注解是Junit下的,然后将类名和方法名加public。
import com.test.demo.bean.Person;
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.SpringRunner;
/*
SpringBoot的单元测试
可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired(required = false)
Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
}
输出如下:
如果使用的是SpringBoot 2.2.6版本的,要将pom文件中的exclusion配置去掉。
3.2 properties配置文件在idea中默认utf-8可能会乱码,调整如下
3.3 注释
3.3.1 @Value获取值和@ConfigurationProperties获取值进行比较
@Value的使用:
@Component
public class Person {
@Value("${person.last-name")
private String lastName;
@Value("#{11*2}")
private Integer age;
...
}
区别:
@ConfigurationProperties | @Value | |
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(驼峰式,下划线,横短线) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验(@Validate) | 支持 | 不支持 |
复杂类型绑定 | 支持 | 不支持 |
配置文件yml还是properties都能获得到值。
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value。
如果说,专门写了一个JavaBean来和配置文件进行映射,就直接使用@ConfigurationProperties。
3.3.2 @PropertySource
@PropertySource:加载指定的配置文件
@PropertySource(value = "{classpath:person.properties}")
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
...
}
3.3.3 @ImportResource
@ImportResource:导入Spring的配置文件,让配置文件里面的文件生效。Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别。想让Spring的配置文件生效,加载进来,将@ImportResource标注在一个配置类上。
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.test.demo.service.HelloService"></bean>
</beans>
注解的使用:
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class DemoApplication {
...
}
3.3.4 @Bean
SpringBoot推荐给容器中添加组件的方式:推荐使用全注解的方式。
(1)配置类@Configuration---》Spring的配置文件
(2)使用@Bean给容器中添加组件
import com.test.demo.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*
@Configuration:指定当前类是一个配置类,就是来替代之前的Spring配置文件
在配置文件使用<bean></bean>标签添加组件
*/
@Configuration
public class MyConfig {
@Bean
public HelloService helloService(){
System.out.println("配置类@Bean给容器中添加了组件....");
return new HelloService();
}
}
3.4 配置文件占位符
3.4.1 随机数
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
3.4.2 占位符获取之前配置的值,如果没有可以是用:指定默认值
person.last‐name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
3.5 Profile
3.5.1 多profile文件
我们在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml。默认使用application.properties的配置。
3.5.2 yml支持多文档块方式
server:
port: 8081
spring:
profiles:
active: prod
‐‐‐
server:
port: 8083
spring:
profiles: dev
‐‐‐
server:
port: 8084
spring:
profiles: prod #指定属于哪个环境
3.5.3 激活指定profile
(1)在配置文件中指定spring.profiles.active=dev
(2)命令行:可以直接在测试的时候,配置传入命令行参数
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
(3)虚拟机参数 :-Dspring.profiles.active=dev
3.6 配置文件加载位置
Spring boot启动会扫描以下位置的application.properties或者application.yml文件作为Spring Boot的默认配置文件。
-file:/config/
-file:./
-classpatg:/config/
-classpath:/
优先级由高到低,高优先级的配置会覆盖低优先级的配置。SpringBoot会从这四个位置全部加载主配置文件。注意是互补配置。还可以通过spring.config.location来改变默认的配置文件位置。
项目打包好以后,可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置,指定配置文件和默认加载的这些配置文件共同作用形成互补配置。
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config=G:/application.properties
3.7 外部配置加载顺序
Spring Boot也可以从以下位置记载配置:优先级从高到低,高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置。
(1)命令行参数:所有的配置都在命令行上进行指定,多个配置用空格分来:--配置项=值
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
(2)来自java:comp/env的INDI属性
(3)Java系统属性(System.getProperties)
(4)操作系统的 环境变量
(5)RandomValuePropertySource配置的random.*属性值
由jar包外向jar包内进行寻找,优先加载带profile
(6)jar包外部的application-{profifile}.properties或application.yml(带spring.profifile)配置文件 jar包外部的application-{profifile}.properties或application.yml(带spring.profifile)配置文件
(7)jar包内部的application-{profifile}.properties或application.yml(带spring.profifile)配置文件
再来加载不带profile
(8)jar包外部的application.properties或application.yml(不带spring.profifile)配置文件
(9)jar包内部的application.properties或application.yml(不带spring.profifile)配置文件
(10)@Configuration注解类上的@PropertySource
(11)通过SpringApplication。setDefaultProperties指定的默认属性
所有支持的配置加载来源。
四.自动配置原理
4.1 自动配置原理
在之前的入门文章中,我们了解了@SpringBootApplication注解中的注解,其中的一个注解就是在SpringBoot启动的时候加载主配置类,开启自动配置功能,这个注解就是@EnableAutoConfiguration。
(1)@EnableAutoConfiguration的作用:
-
利用EnableAutoConfigurationImportSelector给容器中导入组件(这个追溯的步骤可以查看之前的入门文章)
-
先查看selectImports方法:
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
- 点击getAutoConfigurationEntry中,有 这样的代码:
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
- 点击getCondidateConfigurations方法:
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
点击loadFactoryNames方法进行追溯:
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
这里的getSpringFactoriesLoadFactoryClass方法:
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
SpringFatoriesLoader.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.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.ElasticsearchRepositoriesAutoConfi
guration,\
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类都是容器中的一个组件,都加入到容器中,用它们来做自动配置。
4.2 举例
每一个自动配置类进行自动配置功能,以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理。
//表示这是一个配置类,可以给容器中添加组件
@Configuration(proxyBeanMethods = false)
//启动指定类的ConfigurationProperties功能,将配置文件中对应的值和ServerProperties绑定起来,并把ServerProperties加入IOc容器中
@EnableConfigurationProperties(ServerProperties.class)
//Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类的配置就是生效,判断当前应用是否是Web应用,如果是,当前配置生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
//判断当前项目有没有这个类CharacterEncodingFilter,SpringMVC中进行乱码解决的过滤器
@ConditionalOnClass(CharacterEncodingFilter.class)
//判断配置文件中是否存在某个配置,如果不存在,判断也是成立
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
//他已经和SpringBoot配置文件映射
private final Encoding properties;
//只有一个有参构造器的情况下,参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
//给容器中添加一个组件,这个组件的某些值需要从properties中
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
return filter;
}
...
}
根据当前的不同条件判断,决定这个配置类是否生效?一旦这个配置类生效,这个配置类就会给容器中添加各个组件,这些组件的属性值是从对应的properties中获取的(这些类里面的每一个属性是和配置文件绑定的)。
@EnableConfigurationProperties(ServerProperties.class)
所有配置文件能配置的属性都是在xxxProperties类中封装的,配置文件能配置什么就可以参照某个功能对应的属性类。
4.3 细节
上面有提到一个注解是@Conditionala派生注解(Spring注解版原生的@Conditional作用),这个的作用是必须是@Conditional指定的条件成立,才能给容器中添加组件,配置里面的内容才会生效。
@Conditional扩展注解 | 作用(判断是否满足当前指定条件) |
@ConditionalOnJava | 系统的Java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean |
@ConditionalOnMissingBean | 容器中不存在指定的Bean |
@ConditionalExpression | 满足SpEL表达式指定 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 系统中只有一个指定的Bean,或者这个Bean是首选Bean |
@ConditionalOnProperty | 系统指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前是Web环境 |
@ConditionalOnNotWebApplictaion | 当前不是Web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
自动配置类必须在一定的条件下才能生效。那么如何知道哪些自动配置类生效?可以通过启用debug=true属性,来让控制台打印自动配置报告。
4.4 总结
(1)SpringBoot启动时会自动加载大量的自动配置类
(2)我们看我们需要的功能有没有SpringBoot默认写好的自动配置类。
(3)再来看这个自动配置类到底配置了哪些组件(只要我们用的组件有,就不需要再配置)
(4)给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们可以在配置文件中指定这些类的值。
(5)xxxAutoCofiguration自动配置类,给容器中添加组件
(6)xxxProperties封装配置文件中的相关属性