自动配置
SpringBoot启动的时候加载主配置类(@SpringBootApplication注解修饰), @SpringBootApplication开启了自动配置功能 @EnableAutoConfiguration。
@EnableAutoConfiguration作用:利用AutoConfigurationImportSelector给spring容器中导入一些组件。
@SpringBootConfiguration作用:表示类提供springboot应用功能,继@Configuration。
跟踪一下AutoConfigurationImportSelector中的selectImports方法:
扫描所有jar包类路径下 META-INF/spring.factories;
把扫描到的这些文件的内容包装成properties对象;
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们 添加在容器中;
即将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加 入到了容器中。
这里,我们分析一下HttpEncodingAutoConfiguration,其他类似:
@Configuration:
定义配置类。
@EnableConfigurationProperties(HttpEncodingProperties.class):
启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties的属性绑定起来;并把HttpEncodingProperties加入到ioc容器。
@ConditionalOnWebApplication:
判断当前应用是否是web应用,如果是,当前配置类 生效
@ConditionalOnClass(CharacterEncodingFilter.class):
判断当前项目有没有这个类, CharacterEncodingFilter:SpringMVC中解决乱码的过滤器。
@ConditionalOnProperty(prefix="spring.http.encoding",value="enabled", matchIfMissing=true):
//判断配置文件中是否存在某个配置spring.http.encoding.enabled;matchIfMissing表示,即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的;
@Conditional注解(Spring注解版):
条件注解,通过判断类路径下有没有配置相应jar包来确定是否加载和自动配置这个类。
所有在配置文件中能配置的属性都是在xxxxProperties类中封装的,配置文件的配置项 就可以参照其对应的这个属性类,默认就是UTF-8编码。
小结:
1、SpringBoot启动会加载大量的自动配置类;
2、首先检查SpringBoot默认的自动配置类是否满足我们的需求;
3、具体查看这个自动配置类中配置了哪些组件;
4、给容器中的自动配置类添加组件的时候,会从properties类中获取某些属性。我们 就可以在配置文件中指定这些属性的值;
5、xxxxAutoConfigurartion:自动配置类,给容器中添加组件Bean;xxxxProperties:封 装配置文件中相关属性;
Spring Boot提供了对应用进行自动化配置。相比以前 XML 配置方式,很多显式方式申 明是不需要的。二者,大多数默认的配置足够实现开发功能,从而更快速开发。
application.properties添加debug=true,可以在控制台查看自动配置报告信息。
拓展:@Conditional派生注解了解
核心:@Conditional指定的条件成立,才给容器中添加组件,配置类里面的所有内容才 生效;即自动配置类必须在一定的条件下才能生效:
@ConditionalOnJava: 系统的java版本是否符合要求
@ConditionalOnBean: 容器中存在指定Bean;
@ConditionalOnMissingBean: 容器中不存在指定Bean;
@ConditionalOnExpression: 满足SpEL表达式指定
@ConditionalOnClass: 系统中有指定的类
@ConditionalOnMissingClass: 系统中没有指定的类
@ConditionalOnSingleCandidate: 容器中只有一个指定的Bean,或者这个Bean是首 选Bean
@ConditionalOnProperty: 系统中指定的属性是否有指定的值
@ConditionalOnResource: 类路径下是否存在指定资源文件
@ConditionalOnWebApplication: 当前是web环境
@ConditionalOnNotWebApplication: 当前不是web环境
自定义属性(添加新属性、覆盖自动配置默认的属性)
Spring Boot使用默认的全局的配置文件:application.properties 或 application.yml,配置文件名固定。
实例
1、建立PersonProperties
package com.javasgj.springboot.configuration;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.Email;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
/**
* @Validated:对注入的值进行一些简单的校验;
* @Email 校验邮箱地址
* @AssertFalse 校验false
* @AssertTrue 校验true
* @DecimalMax(value=,inclusive=) 小于等于value,inclusive=true,是小于等于
* @DecimalMin(value=,inclusive=) 与上类似
* @Max(value=) 小于等于value
* @Min(value=) 大于等于value
* @NotNull 检查Null
* @Past 检查日期
* @Pattern(regex=,flag=) 正则
* @Size(min=, max=) 字符串,集合,map限制大小
* 这些注解位于javax.validation.constraints包下,校验不通过时抛出异常。
* @Component:作为Bean注入到spring容器,或者使用@Configuration;
* @ConfigurationProperties:将配置文件中以person前缀的属性值自动绑定到对应的字段中;
*/
@Validated
@Component
@ConfigurationProperties(prefix="person")
public class PersonProperties {
private String id;
private String name;
private int age;
private String sex;
@Email
private String email;
private String desc;
private String desc1;
private Map<String, String> maps;
private List<String> list;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getDesc1() {
return desc1;
}
public void setDesc1(String desc1) {
this.desc1 = desc1;
}
public Map<String, String> getMaps() {
return maps;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
@ConfigurationProperties作用:默认加载classpath:application.properties或application.yml,如果同时存在则加载application.properties,并且把文件中以person前缀的属性值自动绑定到对应的l字段中。
当然如果是自定义属性值,也可以使用@PropertySource指定属性文件。
但是要覆盖框架自动配置的属性,只能使用默认的全局配置文件。
2、src/main/resources下建立:application.properties
#properties、yml同时存在,取properties内容
#调试信息,控制台查看自动配置报告信息
#debug=true
#自定义属性
person.name=Jim
person.age=28
person.sex=0
person.email=111@qq.com
#${}占位符,可以引用配置文件其他属性值,如果没有可以配置一个默认值:${person.name:default}
person.desc=I'm ${person.name}
#\n特殊字符,换行
person.desc1=I'm ${person.name} \n welcome!
#map数据类型,对象类型同理:person.对象名.属性名
person.maps.privince=js
person.maps.city=nj
#array、list、set集合
person.list[0]=0
person.list[1]=1
#随机数,通过 RandomValuePropertySource工具类。可以生成随机字符串、随机 int 、随机 long、某范围的随机数
#person.id=${random.int}
#person.id=${random.long}
#person.id=${random.long[1,100]}
#person.id=${random.uuid}
person.id=${random.value}
或者使用application.yml
person:
name: jim1
age: 28
sex: 0
desc1: I am jim \n welcome!
list: [0,1,2]
person.maps: {privince: js, city: nj}
注意:
1、yml格式冒号后面都要一个空格,属性前面也只能添加一个空格,可以使用在线编 辑yml(http://www.bejson.com/validators/yaml_editor/),有校验格式功能。
2、单引号:转义特殊字符,特殊字符只是一个普通的字符串数据,等同于没有引号
name: ‘zhangsan \n lisi’ 输出:zhangsan \n lisi
3、双引号:不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi" 输出:zhangsan
lisi
3、应用启动类
package com.javasgj.springboot.configuration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* spring boot应用启动类
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4、编写测试类
pom.xml引入依赖
<!-- spring boot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
PersonPropertiesTest:
package com.javasgj.springboot.configuration;
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;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=Application.class)
public class PersonPropertiesTest {
@Autowired
PersonProperties personProperties;
@Test
public void testGetName() {
/**
* springboot默认以ISO-8859-1编码读取properties文件内容,所以会有中文乱码,我们可以做如下处理解决乱码,
* 或者使用yml类型文件进行配置,没有中文乱码问题。
*/
/*try {
System.out.println(new String(personProperties.getName().getBytes("ISO-8859-1"), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}*/
System.out.println("结果:" + personProperties.getId());
System.out.println("结果:" + personProperties.getName());
System.out.println("结果:" + personProperties.getEmail());
System.out.println("结果:" + personProperties.getDesc1());
System.out.println("结果:" + personProperties.getMaps().keySet().toString());
System.out.println("结果:" + personProperties.getList().size());
}
}
@SpringBootTest指定应用启动类Application
赶紧运行结果看看吧!
扩展:
Spring Boot不单单从application.properties获取配置,我们可以在程序中设置多种 配置属性。按照以下列表的优先级从高到低排列:
1、命令行参数
2、java:comp/env 里的 JNDI 属性
3、JVM 系统属性
4、操作系统环境变量
5、RandomValuePropertySource 属性类生成的 random.* 属性
6、应用外部的application-{profile}.properties或application.yml(带spring.profile)文件
7、应用内部的application-{profile}.properties或application.yml(带spring.profile)文件
6、应用以外的 application.properties(或 yml)文件
7、应用内部的 application.properties(或 yml)文件
8、在应用 @Configuration 配置类中,用 @PropertySource 注解声明的属性文件
9、SpringApplication.setDefaultProperties 声明的默认属性
注意一些特殊属性如:user.name,如果你在配置文件配置了此属性,但是确获取不到 配置文件中的值,为什么呢?因为系统属性有user.name,优先级又高,会获取到机器 当前用户账号。