Spring @ConfigurationProperties源码详解(1)

概述
之前介绍过Spring中的配置类@Configuration,在配置类中通过注入Environment或者@Value,我们可以拿到外部配置数据。在Spring boot中,框架默认提供了application,properties配置文件来提供系统配置,那么有没有更好的办法来获取外部配置呢? 那就是@ConfigurationProperties。

应用示例
1、我们在类路径下新建一个配置文件:test.properties
test.data = hello
test.num = 10


2、新建配置属性文件: AppConfigProperties.java
@ConfigurationProperties (prefix = "test" ,locations = "classpath:test.properties" )
public class AppConfigProperties {
private String data ;
private int num ;
//忽略getter & setter
}
我们来看注解使用的参数,prefix代表配置前缀,前缀和属性名称对应于配置文件的key,容器会自动绑定配置文件的数据到对应的配置属性类中。locations 属性指向了配置文件的路径。

3、新建配置类: AppConfig.java
@Configuration
@EnableConfigurationProperties (AppConfigProperties. class )
public class AppConfig {
@Autowired
public AppConfigProperties properties ;

}
我们在配置类中使用了 @EnableConfigurationProperties来激活配置属性,注解的属性申明了配置属性类 AppConfigProperties. class,最后我们只要把 AppConfig注册到应用上下文即可。

4、测试主类:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig. class );
context.refresh();
AppConfig appConfig = context.getBean(AppConfig. class );
System. out .println(appConfig. properties .getData());
System. out .println(appConfig. properties .getNum());

就可以直接访问到属性配置绑定之后的数据了。

@ConfigurationProperties源码解析
现在让我们来抽丝剥茧,看看整个配置属性类和数据绑定是如何工作的。先看一下@ConfigurationProperties的源码:

@Target ({ ElementType. TYPE , ElementType. METHOD })
@Retention (RetentionPolicy. RUNTIME )
@Documented
public @ interface ConfigurationProperties {
@AliasFor ( "prefix" ) //前缀,互为别名
String value() default "" ;

@AliasFor ( "value" ) //前缀,互为别名
String prefix() default "" ;
// 是否忽略非法的属性,通常指类型不匹配,无法绑定数据到成员
boolean ignoreInvalidFields() default false ;
// 是否忽略嵌套的数据
boolean ignoreNestedProperties() default false ;
// 是否忽略未知的属性
boolean ignoreUnknownFields() default true ;
// 非法属性是否抛出异常
boolean exceptionIfInvalid() default true ;
// 搜速路径,因改为使用environment的路径,所以被标记过期
@Deprecated
String[] locations() default {};
// 是否和默认的配置项合并
@Deprecated
boolean merge() default true ;
}

除了最常用的prefix前缀配置,其它属性通常保持默认即可。

神奇的@EnableConfigurationProperties
不像之前的@Configuration配置注解,@ConfigurationProperties注解并没有@Component元注解,因此直接注册配置属性类并不会有任何效果。例如执行下面的代码:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfigProperties. class );
context.refresh();
AppConfigProperties appConfigProperties = context.getBean(AppConfigProperties. class );
--null
--0
只会创建普通的bean实例,上下文默认不会去解析注解,也不会做响应的数据绑定。真正的秘密隐藏在 @EnableConfigurationProperties里面,我们来调整一下上面的例子:

@ConfigurationProperties (prefix = "test" ,locations = "classpath:test.properties" )
@EnableConfigurationProperties
public class AppConfigProperties {
private String data ;
private int num ;
//忽略getter & setter
}

再执行上面的代码:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfigProperties. class );
context.refresh();
AppConfigProperties appConfigProperties = context.getBean(AppConfigProperties. class );
--hello
--10
发现配置数据正确的绑定到了配置属性对象。从注解名字Enable也可以看出,这个注解是一个开关注解,从而启用了对所有标注 @ConfigurationProperties的数据绑定处理。开关注解仅需执行一次即可,例如我们可以新建一个类 EnableSwitch.java
@EnableConfigurationProperties ()
public class EnableSwitch {
}

就算配置属性类没有标记 @EnableConfigurationProperties注解,之后加载所有标注 @ConfigurationProperties注解的bean都会正确绑定配置数据。
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(EnableSwitch. class );
context.register(AppConfigProperties. class );
context.refresh();
AppConfigProperties appConfig = context.getBean(AppConfigProperties. class );
--hello
--10

你可能感兴趣的:(spring)