SpringBoot(二)

SpringBoot(二)

自动配置原理

pom.xml

  • spring-boot-dependencies:核心依赖在父工程中
  • 我们在引入一些Spring Boot不需要指定版本,就是因为有这些版本仓库

启动器

  • <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    
  • 指定了Spring Boot的启动场景

  • 比如spring-boot-starte-web就会自动导入web环境的所有依赖

  • Spring Boot会将所有的功能场景,都编程一个个的启动器

    主程序:

  • 注解:

    • @SpringBootApplication标注这个类是一个Spring Boot应用
      • @SpringBootConfiguration:Spring Boot配置
        • @Configuration:Spring配置类
          • @Component:Spring组件
      • @EnableAutoConfiguration:自动配置
        • @AutoConfigurationPackage:自动配置包
          • @Import({Registrar.class}):自动配置包注册
        • @Import({AutoConfigurationImportSelector.class}):自动导入选择器
          • List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);:获取所有配置
  • 获取候选配置:

    • protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
              List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
              Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
              return configurations;
          }
      
      
      •  protected Class<?> getSpringFactoriesLoaderFactoryClass() {
             return EnableAutoConfiguration.class;
         }
        
        • 启动类下的所有资源被导入
      • META-INF/spring.factories:自动配置的核心文件

        • External Libraries -> Maven: org.springframework.boot:spring-boot-autoconfiguration -> META-INF -> spring.factories
      • loadFactoryNames

        • loadSpringFactories

          • URL url = (URL)urls.nextElement();
            UrlResource resource = new UrlResource(url);
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            
          • 所有资源加载到配置类中

  • @ConditionaOnXXX:核心注解,满足条件才生效

    • 因此需要导入对应的starter,自动配置才能生效

主启动类

SpringApplication的实例化

  • 推断应用的类型是普通的项目还是Web项目
  • 查找并加载所有可用初始化器,设置到initializers属性中
  • 找出所有的应用程序监听器,设置到listeners属性中
  • 推断并设置main方法的定义类,找到运行的主类

run方法的执行

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
    ConfigurableApplicationContext context = null;
    this.configureHeadlessProperty();
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);

    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        this.configureIgnoreBeanInfo(environment);
        Banner printedBanner = this.printBanner(environment);
        context = this.createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        this.refreshContext(context);
        this.afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }

        listeners.started(context);
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, listeners);
        throw new IllegalStateException(var10);
    }

    try {
        listeners.running(context);
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}

YAML

配置文件

  • Spring Boot使用一个全局的配置文件,名字固定

    • application.properties
      • 语法结构:key=value
    • application.yaml
      • 语法结构:key:[空格]value
  • 配置文件的作用:修改Spring Boot自动配置的默认值

简介

  • YAML Ain't a Markup Language,YAML不是一种标记语言
  • Yet Another Markup Language,仍是一种标记语言

语法

key: value
  • 以此来表示一对键值对(空格不能省略)

  • 以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的

  • 属性的值和大小写都是敏感的

  • 常用写法:

#普通key-value
name: yhr
##对象
student1:
    name: yhr
    age: 3
##行内写法
student2: {name: yhr, age: 3}
##数组
pets1:
  - cat
  - dog
  - pig
##行内写法
pets2: [cat, dog, pig]

实现属性注入

  • Spring中提供Value注解实现属性注入,但YAML可以实现批量注入松散绑定(横杠和驼峰命名法一致)、JSP303数据校验复杂类型封装等功能,只是不支持SpEL(Spring Expression Language)
  • 编写实体类,除开lombok的注解外,@Component表示是一个Spring组件,@ConfigurationProperties(prefix = "person")表示从YAML配置文件中的person对象取值
//Person.java
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birth;
    private Map<String, Object> map;
    private List<Object> list;
    private Dog dog;
}

//Dog.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class Dog {
    private String name;
    private Integer age;
}

  • 编写application.yaml配置文件
person:
  name: yhr
  age: 23
  happy: false
  birth: 2021/2/11
  map: {k1: v1, k2: v2}
  list:
    - coding
    - music
    - girl
  dog:
    name: 小白
    age: 3
  • 测试,需要用@Autowired注解实现自动注入
@Autowired
private Person person;

@Test
void contextLoads() {
    System.out.println(person);
}
  • 注意,导入一下依赖,可以让@ConfigurationProperties注解有提示,但不导入也不影响使用
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
  • YAML中可以用${random.int}${random.uuid}等随机值,也可以使用${person.hello:defaultValue}在前面的值不存在时取默认值

JSR303校验

  • 导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • 实体类上加入@Validated注解
  • 属性上加注解限制其赋值,如@Email(message = "邮箱格式错误")
  • 还可以使用@NotNull@Min(value)@Max(value)@Size(max, min)
  • 甚至能使用正则表达式@Pattern(value)

配置文件位置

  • 多个配置文件优先级按以下顺序:

    • 项目目录
      • file: ./config/
      • file: ./
    • resources目录
      • classpath:/config/
      • classpath:/
  • 多环境配置(properties):

    • application.properties中的spring.profiles.active属性选择激活哪个配置文件,对应文件需在同目录下,且名为application-xxx.properties,属性值只需写xxx即可
  • YAML的多环境配置:

spring:
  profiles:
    active: xxx
posted @ 2021-02-11 16:33  一天到晚睡觉的鱼  阅读(52)  评论(0)    收藏  举报