一、主启动类

1. 加载多个组件

  • 根据项目中引入的starter,将该starter场景下的bean加载进容器中
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 得到一个容器,容器只存放着对应的starter下面的所有组件
        ConfigurableApplicationContext container = SpringApplication.run(Application.class);
        String[] beansArray = container.getBeanDefinitionNames();
    }
}

2. 默认包结构

- 无须显式化  : ComponentScan
- 默认扫描spring注解的包结构: 启动类所在包及其下面的子包结构
- 如需改变包扫描位置,在主启动类上增添属性
@SpringBootApplication(scanBasePackages="com.day")

3. 自动配置

  • spring的所有的starter对应的自动配置都集中在:spring-boot-autoconfigure包下,但只有引入了哪个starter,才会去加载对应包下的组件,没有加载的会报红
  • 默认配置: application.yaml中的所有的属性,都是对应到一个class中,并且会将该类的bean注入到容器中

二、常用注解

1. configuration + bean

1.1 普通使用
/**告诉spring-boot: 这是一个配置类,并且为单例*/
@Configuration
public class EntityConfigure {

    /**将方法的返回值放在容器中,默认以方法名作为组件名,默认单例*/
    @Bean
    public Pet getPet() {
        return new Pet();
    }

    @Bean
    public Fruit getFruit() {
        return new Fruit();
    }
}
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 得到一个容器,容器只存放着对应的starter下面的所有的组件
        ConfigurableApplicationContext container = SpringApplication.run(Application.class);
        System.out.println(container.getBean(Pet.class));
        System.out.println(container.getBean("getFruit"));
    }
}
1.2 full模式/lite模式
  • proxyBeanMethods = true(默认为true):full模式
  • 则该配置类为代理组件,调用该组件内部方法时,先判断容器中是否存在该容器, 如果有,则直接去容器中取,如果没有才会去创建
@Configuration(proxyBeanMethods = true)
public class EntityConfigure {

    @Bean
    public Pet getPet() {
        return new Pet();
    }

    @Bean
    public Fruit getFruit() {
        return new Fruit();
    }
}
  • proxyBeanMethods = false:lite模式
  • 直接调用EntityConfigure组建中的方法,不会去容器判断
@Configuration(proxyBeanMethods = false)
public class EntityConfigure {

    @Bean
    public Pet getPet() {
        return new Pet();
    }

    @Bean
    public Fruit getFruit() {
        return new Fruit();
    }
}

2. Import

  • 将该类放在容器中,该类不需要其他注解
  • 配置在任何组件类上,如configuration , controller上
  • 可以用来导入自己的项目类,也可以导入第三方类库,使用无参构造来创建对象
@Import({Pet.class, Fruit.class, DBHelper.class})

3. Conditional

  • 该注解为spring注解,springboot根据此注解衍生出了很多注解
  • 部分注解牵涉到组建注册的先后顺序问题
@Configuration
public class MyConfig {

    @Bean
    public Fruit getFruit(){
        return new Fruit();
    }

    /**方法上: 如果容器中有某个组件,bean注解才会生效
     *        1. 容器加载顺序从上到下,这两个bean的代码位置不能变化*/
    @ConditionalOnBean(Fruit.class)
    @Bean
    public Pet getPet() {
        return new Pet();
    }
}
//  加在类上,如果成立,则该类下面的bean注解可以生效,否则不生效
@Configuration
@ConditionalOnBean(HelloController.class)
public class MyConfig {

    @Bean
    public Fruit getFruit(){
        return new Fruit();
    }

    @Bean
    public Pet getPet() {
        return new Pet();
    }
}

4. application属性绑定

  • 将类与application文件中的属性进行绑定
4.1 ConfigurationProperties + Component
# 只能加载名字为application的配置文件;
@ConfigurationProperties(prefix = "people")
people:
  email: 1037289945@qq.com
  name: 'lucy'
  age: 20
  boss: true
  birthday: 2020/05/07

  map: {key1: value1, key2: value2, key3: value3}
  list:
    - heihei
    - haha
    - hehe

  strArr: [apple, peach, melon]

  employee:
    age: 100
    name: "shuzhan"
/**1. @ConfigurationProperties: 告诉springboot将本类中的属性同配置文件映射
 *                      prefix: 配置文件同people开始的标签进行映射
 * 2. 字段名称必须和配置文件中的一致
 * 3. @Validated, @Email 确保注入的数据必须是邮箱格式*/
@ConfigurationProperties(prefix = "people")
@Component
@Validated
public class People {

    @Email
    private String email;
    
    private String name;

    private Integer age;

    private Boolean boss;

    private Date birthday;

    private Map<String,Object> map;

    private List<String> list;

    private String[] strArr;

    private Employee employee;

}
4.2. Value + Component
@Component
public class Student {

    /**1. 通过spring的el表达式, 去application命名的配置文件中去找
     * 2. #{} : 直接数据进行注入
     * 3. 直接注入字符串,其中value可以省略*/
    @Value("${people.name}")
    private String name;

    @Value("#{20+20}")
    private Integer age;

    @Value( value = "true")
    private Boolean boss;

    @Value("2010/04/05")
    private Date birthday;

}

ConfigurationProperties

@Value

支持数据校验

不支持数据校验

批量注入数据

单个注入数据

支持复杂数据类型Map,list,数组,对象等

不支持复杂数据类型

4.3 ConfigurationProperties + EnableConfigurationProperties
  • 上面1,2的另外一种写法
@ConfigurationProperties(prefix = "aws")
@Data
public class AWSConfig {
    private String region;
    private String password;
}
@Configuration
//  可以将第三方的类加载到该容器中
@EnableConfigurationProperties(AWSConfig.class)
public class MyConfig {

}

5. 其他配置文件属性绑定

  • PropertySource + ConfigurationProperties + Component
  • 加载指定名称的配置文件

jdbc.properties

jdbc.driverClass = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://10.5.16.76:3306/stu_db
jdbc.username = root
jdbc.password = 123456
package com.zte.business.bo;

/**  可以加载多个配置文件
 * */
@PropertySource(value = {"classpath:jdbc.properties"})
@Component
@ConfigurationProperties(prefix = "jdbc")
public class JDBC {
    private String diverClass;
    private String url;
    private String username;
    private String password;
}

6. yaml文件赋值

  • 可以通过占位符,随机数等操作,在配置文件中为某个字段进行赋值;
  • 适用于yaml/yml/properties;
people:
  name: ${random.uuid}
  age: ${random.int}
  boss: true
  email: ${people.age}_1037289945@qq.com
  birthday: 2020/05/07

  map: {key1: value1, key2: value2, key3: value3}
  list:
    - heihei
    - haha
    - hehe

  strArr: [apple, peach, melon]

# ${people.hehe}_dog: 找不到就把这个表达式直接转换为字符串赋值
# ${people.hehe:jacksparrow}_dog: 如果没有该数据,则给一个默认值
  employee:
    age: 100
    name: ${people.hehe:jacksparrow}_dog