这个特性的其实还得归纳到@Autowired的特性上,或者说@Autowired包涵了一些我们不知道的能力。
@Autowired
private Map<String, BaseValidateCodeGenerator> baseValidateCodeGenerators;
在Spring中,写这种形式的代码,spring能自动装配值到map中,这种装配不是简单的给Map赋值,而是往Map里塞入元素,塞入规则需要看源码。我们平时可以适当利用这种特性来简化业务代码的编写。具体实现方式在DefaultListableBeanFactory#doResolveDependency()中。总结来说规则就是:
1、如果是数组,则获取数组元素类型,查找匹配该类型的所有bean,返回一个这些bean的数组;
2、如果该类可赋给Collection,并且是一个接口,则获取集合元素类型,查找匹配该类型的所有bean,返回一个这些bean的集合;
3、如果该类型是Map(注意是type == Map.class),且key是String类型,则获取Map的value的类型,查找匹配该类型的所有bean,这是一个key为bean name、value为bean实例的一个Map,返回这个Map。
4、其他情况则是我们所熟知的按类型自动装配过程。
一、使用@ConfigurationProperties
如果配置文件是这样的:
api:
a:
in:
publicKey: ipk1
privateKey: isk1
out:
publicKey: opk1
privateKey: osk1
b:
in:
publicKey: ipk2
privateKey: isk2
out:
publicKey: opk2
privateKey: osk2
SpringBoot配置文件的特点是key=value形式,但是允许层级嵌套,嵌套以后,情况就变复杂了。
以上面配置为例:最外层的key肯定是一个变量,名字就是api,api的类型是什么,取决于api下面的配置项,我们可以看到,a,b,c......很明显在随业务增多而变化,所以这个层级需要一个Map,紧接着in、out这个层级,这些key都是固定的了,此时就知道这些是变量名称了。具体类型如下:
@Component
@ConfigurationProperties
@Data
public class TestProperties {
Map<String, AllKey> api;
@Data
public static class AllKey {
private Key in;
private Key out;
}
@Data
public static class Key {
private String publicKey;
private String privateKey;
}
}
这样配置就自动注入进去了。这就是约定的巨大作用。