springboot 基础

配置

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 根据这里配置的路径进行扫描和排除,默认是启动类同级及其子包
posted @ 2021-08-17 15:06  huanggy  阅读(44)  评论(0编辑  收藏  举报