配置
application.properties 优先于 application.yml
properties 属性值不支持map、数组等,yml 可以
读取默认配置文件(基本类型)
直接在 application.yml 添加,程序中通过 @Value 读取(只能是基本类型)
读取默认配置文件(复杂类型)
直接在 application.yml 添加,使用一个 java 类来映射
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private int id;
private String name;
private List<String> hobby;
private String[] family;
private Map map;
private Pet pet; // 需要创建一个 Pet 类
}
person:
id: 1
name: Milk
bobby: [吃饭, 睡觉, 打豆豆]
family: [father, mother]
map: {k1: v1, k2:v2}
pet: {type: dog, name: 旺财} # 会根据 Pet 类自动映射
<!-- 自定义配置属性不会提示,如果想要提示导入这个依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
读取非默认配置文件
- resource 下创建一个 test.properties 文件
test.id=110
test.name=test
@Configuration
@PropertySource("classpath:test.properties") // 指定自定义配置文件位置和名称
@EnableConfigurationProperties(MyProperties.class) // 开启对应配置类的属性注入功能
@ConfigurationProperties(prefix = "test") // 指定配置文件注入属性前缀
public class MyProperties {
private int id;
private String name;
}
注解完成配置
不依赖配置文件,使用 @Configuration(类) 和 @Bean(方法)完成
// 定义该类是一个配置类
@Configuration
public class MyConfig {
// 将返回值对象作为组件添加到Spring容器中,该组件id默认为方法名
@Bean
public MyService myService(){
return new MyService();
}
}
自动配置(启动流程)
/**
* SpringbootApplication 定义
*
* 除开元注解,主要关注 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 三个注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootConfiguration{}
1,@SpringBootConfiguration
1,作用和 @Configuration 相同,换个名子包装一下而已
2,正因如此可以直接在启动类里使用 @Bean 直接定义 bean
2,@EnableAutoConfiguration
1,表示开启自动配置功能,简单说就是自动创建一些 bean
2,@Configuration 和 @Compoment 等自己写的 bean 由 @AutoConfigurationPackage 实现
3,别的需要的 bean 由 @Import(AutoConfigurationPackages.Registrar.class) 实现
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration{}
2.1,@AutoConfigurationPackage
1,由 @Import(AutoConfigurationPackages.Registrar.class) 注解导入 Registrar 类
2,Registrar 的作用是通过 registerBeanDefinitions 方法把启动类同级及子包的配置类(@Configure注解的类)加入到容器中
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class) // 导入 Registrar 中注册的组件
public @interface AutoConfigurationPackage {}
// AutoConfigurationPackages.Registrar
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// debug 模式断点可以发现 new PackageImports(metadata).getPackageNames() 是启动类所在的包路径
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
2.2,@Import(AutoConfigurationImportSelector.class)
- 将 AutoConfigurationImportSelector 导入到 spring 容器中
- AutoConfigurationImportSelector 类作用
是通过 selectImports 方法来导入组件
- selectImports 方法使用内部工具类 SpringFactoriesLoader 加载 spring.factories 文件,spring.factories 就是所有能自动配置的类
- 并不是所有的类都会配置,每个配置类都有 @ConditionalOnClass 注解,这个注解决定当前类是否自动配置,具体是判断当前类是否存在(导入了 maven 依赖就存在)
// AutoConfigurationImportSelector.selectImports
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 调用 getAutoConfigurationEntry
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
// AutoConfigurationImportSelector.getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 获取 EnableAutoConfiguration 注解的 exclude 和 excludeName 属性值
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 获取 spring.factories 中 EnableAutoConfiguration 的配置值,这些就是能自动配置的类(spring-boot-autoconfigure jar 下 META-INF/spring.factories)
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 去重
configurations = removeDuplicates(configurations);
// 获取不自动装备的类,根据 EnableAutoConfiguration 注解值
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 检查不自动装备的类是否必须存在,如果是则抛出异常
checkExcludedClasses(configurations, exclusions);
// 这里才正式排除
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
3,@ComponentScan
指定路径,@EnableAutoConfiguration 根据这里配置的路径进行扫描和排除,默认是启动类同级及其子包