# @PropertySource 和 @ConfigurationProperties 区别
@ConfigurationProperties
@ConfigurationProperties 是 springboot 中注解,用于将主配置文件 (application.properties 或者 “application.yml” ) 中的属性,映射到实体类中对应的属性。
意思就是把主配置文件中配置属性设置到对应的 Bean 属性上。
常见使用方式:
- @ConfigurationProperties + @Component 注解到 bean 定义类上
- @ConfigurationProperties + @Bean 注解在配置类的 bean 定义方法上
- @ConfigurationProperties 注解到普通类然后通过 @EnableConfigurationProperties 定义为 bean
@Bean,@Component 这种我们可以理解,两个注解都能标识一个 Bean.
@EnableConfigurationProperties 是如何让其成为一个 bean 的呢?
@EnableConfigurationProperties 源码分析:
@EnableConfigurationProperties 注解会导入一个 EnableConfigurationPropertiesImportSelector 类,其 selectImports 方法返回的类,将注册为 beandefinition。
@Override | |
public String[] selectImports(AnnotationMetadata metadata) { | |
获取@EnableConfigurationProperties的参数信息 | |
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes( | |
EnableConfigurationProperties.class.getName(), false); | |
Object[] type = attributes == null ? null | |
: (Object[]) attributes.getFirst("value"); | |
参数没有值,注册1个 | |
if (type == null || type.length == 0) { | |
return new String[] { | |
ConfigurationPropertiesBindingPostProcessorRegistrar.class | |
.getName() }; | |
} | |
参数有值,注册两个 | |
return new String[] { ConfigurationPropertiesBeanRegistrar.class.getName(), | |
ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() }; | |
} |
总的来说会注册两个类:
- ConfigurationPropertiesBindingPostProcessorRegistrar
- ConfigurationPropertiesBeanRegistrar
- ConfigurationPropertiesBindingPostProcessorRegistrar: 看名字我们也可以看出 ConfigurationPropertiesBindingPostProcessor 注册器,没错就是用来注册 ConfigurationPropertiesBindingPostProcessor 这个 BeanPostProcessor 的。BeanPostProcessor 会在创建 bean 的时候,被执行处理 Bean 相关信息。ConfigurationPropertiesBindingPostProcessor 这个 BeanPostProcessor 是就是用来解析 Bean 上的 @ConfigurationProperties 注解的。
ConfigurationPropertiesBindingPostProcessor 会检查 Bean 是否有 @ConfigurationProperties,如果有就绑定相关配置属性到本 bean 的相关属性上。
- ConfigurationPropertiesBeanRegistrar: 看名字,ConfigurationPropertiesBean 注册器,ConfigurationPropertiesBeanRegistrar 是在 @ConfigurationProperties 的 value 属性有值的情况下注册的。
例如:
@EnableConfigurationProperties({ EurekaDashboardProperties.class, | |
InstanceRegistryProperties.class }) |
ConfigurationPropertiesBeanRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,所以他的 registerBeanDefinitions 方法,也会注册 Bean. 注册就是 @EnableConfigurationProperties 的 value 值,例如例子中 EurekaDashboardProperties.class,InstanceRegistryProperties.class
由此我们可以看出:
@Component, @Bean , ConfigurationPropertiesBeanRegistrar 都是为了告诉 spring,对应的类是一个 Bean,spring 要去加载,解析,创建 Bean.
而 ConfigurationPropertiesBindingPostProcessor 的工作就是完成配置信息到 Bean 属性的绑定工作。
@EnableConfigurationProperties 的目的
- 保证容器中有解析 ConfigurationProperties 注解的 BeanPostProcessor
- 向容器内注入 value 对应的 BeanDefinition
idea 中,在主配置文件 ctrl + 鼠标 能看到这对应的属性被哪个 @ConfigurationProperties 修饰的属性类使用
@ConfigurationProperties 是针对主配置文件的。但是我们不想所有的配置都放到主配置文件中怎么办????
@PropertySource
@PropertySource 是 spring 的注解
加载指定的属性文件的配置到 Spring 的 Environment 中。可以配合 @Value 和 @ConfigurationProperties 使用。
用法:
- @Configuration+ @PropertySource+Environment
- @Configuration+ @PropertySource+@Value
- @Configuration+ @PropertySource+@ConfigurationProperties
@Configuration 本质也是告诉 spring 这是一个 bean.
my.name=helloworld | |
my.age=8 |
@Configuration+ @PropertySource+Environment
@Configuration | |
@PropertySource("classpath:hellword.properties") | |
public class HelloWorldConfig { | |
@Autowired | |
private Environment env; | |
} |
@Configuration+ @PropertySource+@Value
@Configuration | |
@PropertySource("classpath:hellword.properties") | |
public class HelloWorldConfig { | |
@Value(${my.name}) | |
private String name; | |
} |
@Configuration+ @PropertySource+@ConfigurationProperties
@PropertySource 指定加载哪个文件,@ConfigurationProperties 指定加载文件中的哪一类属性。
@PropertySource+@ConfigurationProperties 在一起解决了 @ConfigurationProperties 只能加载主文件内属性问题。
@Configuration | |
@PropertySource("classpath:hellword.properties") | |
@ConfigurationProperties(prefix = "my") | |
public class HelloWorldConfig { | |
private String name; | |
} |
# 总结:
灵活利用这两个注解,能够把配置信息安排有层次感