本来在controller文件中是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
public class HelloController {

@Valid("${minMoney}")
private BigDecimal minValue;

@Valid("${maxMoney}")
private BigDecimal maxValue;

@Valid("${description}")
private String description;

@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String say() {
return ...
}

对应的yml配置是:

1
2
3
4
5
6
7
8
9
server:
port: 8081
servlet:
context-path: /luckymoney


minMoney: 0.01
maxMoney: 9999
description: minvalue would be $1

如果配置中的字段越来越多,那么在controller中对应配置字段的类属性也越来越多,重复写@Valid很多: 为了避免这种问题, 更好的方式是把现在controller中的类属性全部放在一个类中,这样配置的时候只用配置这个类,只用写一次注解,不用重复写多次@Valid.

改配置为:

1
2
3
4
5
6
7
8
9
server:
port: 8081
servlet:
context-path: /luckymoney

limit:
minMoney: 0.01
maxMoney: 9999
description: minvalue would be $1

HelloController同级目录下创建文件LimitConfig,注意注解@ConfigurationProperties的参数prefix,要和配置那个结构体名称对应起来

1
2
3
4
5
6
7
8
9
10
11
@ConfigurationProperties(prefix = "limit")
public class LimitConfig {

private BigDecimal minMoney;

private BigDecimal maxMoney;

private String description;

// getters and setters
}

此时controller为:

1
2
3
4
5
6
7
8
9
10
@RestController
public class HelloController {

@Autowired
private LimitConfig limitConfig;

@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String say() {
return limitConfig.getDescription();
}

也就是@Autowired都是用来注解类的(其实最多是用来装配POJO的), 此时运行会报错Could not autowire. No beans of 'LimitConfig' type found.这是因为spring容器并不知道这个类是什么东西,要用@Component告诉容器可以自动装配这个类,从而把这个POJO变成bean:

1
2
3
4
5
6
7
8
9
10
11
12
@Component
@ConfigurationProperties(prefix = "limit")
public class LimitConfig {

private BigDecimal minMoney;

private BigDecimal maxMoney;

private String description;

// getters and setters
}

仔细一想,autowired实际上是完成了把POJO变成bean的第二步。bean的来源都是两步:

  1. 定义好POJO;
  2. dependency injection;

第二步如果手动写,我记得是要用另一个config类注解@ComponentScan配合POJO类的@Component, 这里@Autowired就自动装配自动扫描存在的component从而注入得到bean。