如果一个bean已经用@ConfigurationProperties进行了注解,那么@EnableConfigurationProperties有什么区别呢?
如果一个bean已经用@ConfigurationProperties进行了注解,那么@EnableConfigurationProperties有什么区别呢?
Spring Boot文档指出,要使用@ConfigurationProperties注解,还需要在@EnableConfigurationProperties注解中列出要注册的属性类,如下所示:
@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}
但在接下来的段落中又指出:
即使前面的配置为AcmeProperties创建了一个普通的bean,我们还是建议@ConfigurationProperties仅处理环境,特别是不要从上下文中注入其他bean。话虽如此,@EnableConfigurationProperties注解也会自动应用于您的项目,以便从Environment中配置任何已使用@ConfigurationProperties注解的现有bean。
这意味着在@EnableConfigurationProperties注解下列出@ConfigurationProperties bean是不必要的。
那么到底是哪种情况呢?根据实验证明,如果我使用@ConfigurationProperties注解注释一个bean,它会如预期地被注入属性,而不需要将其列在@EnableConfigurationProperties中。但如果是这样的话,为什么在文档中要列出任何使用@ConfigurationProperties注解的内容呢?这是否有任何区别呢?
@EnableConfigurationProperties注解的作用是将一个配置类与Spring的配置标注(@ConfigurationProperties)绑定起来,以便在注入服务时可以轻松获取配置属性。但是,如果一个bean已经使用@ConfigurationProperties注解进行了注解,那么@EnableConfigurationProperties注解会有什么不同呢?
问题的出现原因是@EnableConfigurationProperties注解和@ConfigurationProperties注解都可以用于绑定配置属性,因此在某些情况下可能会导致重复的配置绑定。为了解决这个问题,我们可以采取以下方法:
1. 如果一个bean已经使用@ConfigurationProperties注解进行了注解,并且没有使用@EnableConfigurationProperties注解,那么不需要再使用@EnableConfigurationProperties注解。
2. 如果一个bean已经使用@ConfigurationProperties注解进行了注解,并且同时使用了@EnableConfigurationProperties注解,那么@EnableConfigurationProperties注解将会覆盖@ConfigurationProperties注解的配置绑定。
3. 如果一个bean已经使用@EnableConfigurationProperties注解进行了注解,并且没有使用@ConfigurationProperties注解,那么@EnableConfigurationProperties注解将会生效并绑定配置属性。
对于已经使用@ConfigurationProperties注解的bean,使用@EnableConfigurationProperties注解将会覆盖@ConfigurationProperties注解的配置绑定。
@EnableConfigurationProperties注解的作用是告诉Spring将带有@ConfigurationProperties注解的类注册为Bean,并将其作为应用程序.yml/properties文件值的使用者。它还可以指定这个类表示的部分。
如果不需要指定属性文件的部分,就可以省略@EnableConfigurationProperties注解。该注解用于启用@ConfigurationProperties的支持,一个应用程序中只能存在一次,通常位于主类上,不应该出现在其他类上。
那么作为@EnableConfigurationProperties注解的参数给出的类的作用是什么呢?它们指示Spring应该启用哪些@ConfigurationProperties。如果希望加载Spring能够找到的所有@ConfigurationProperties,就不需要提供任何类作为参数。
@EnableConfigurationProperties会为@ConfigurationProperties注释的bean启用支持。如果你查看注释的Java Doc,你会看到:
启用对@ConfigurationProperties注释的bean的支持。可以通过标准方式注册@ConfigurationProperties bean(例如使用@Bean方法),或者为方便起见,可以直接在此注释上指定。
例如,假设你有一个类,其职责是从你的application.yml / application.properties中读取和存储信息,这些信息是连接到不同数据库所需的。你用@ConfigurationProperties注释它。
然后,你通常有一个@Configuration注释的类,它提供了一个DataSource Bean给你的应用程序。你可以使用@EnableConfigurationProperties将它链接到@ConfigurationProperties注释的类,并相应地初始化你的数据源。
这里是一个小例子:
application.yml
data-sources:
db1:
url: "jdbc:postgresql://localhost:5432}/db1"
username: test
password: test
db2:
url: "jdbc:postgresql://localhost:5432}/db2"
username: test
password: test
DataSourcesConfiguration
public class DataSourcesConfiguration { private MapdataSources; public void setDataSources(Map dataSources) { this.dataSources = dataSources; } Map getDataSources() { return dataSources; } }
DataSourceConnectionConfiguration
@DataSourcesConfiguration public class DataSourceConnectionConfiguration implements Provider{ private DataSourcesConfiguration dataSourcesConfiguration; public DataSourceConnectionConfiguration(DataSourcesConfiguration dataSourcesConfiguration) { this.dataSourcesConfiguration = dataSourcesConfiguration; } public DataSource dataSource() { // Use dataSourcesConfiguration to create application data source. E.g., a AbstractRoutingDataSource.. } }
那么,与将注释留空相比,包含DataSourcesConfiguration.class在@EnableConfigurationProperties注释中有什么不同吗?
DataSourcesConfiguration.class不会被注册为Spring Bean。因此,如果你移除注释的值,在这种情况下是DataSourcesConfiguration.class,Spring将无法找到它。如果你检查::value()的文档,它说这只是一种快速注册@ConfigurationProperties注释的bean的便捷方式。如果DataSourcesConfiguration被注释为,例如,@Component注释,它会将其注册为Spring Bean,我们可以将注释留空。希望对你有所帮助!
方便的是,@EnableConfigurationProperties是元注释了@ConfigurationProperties,因此如果你在保存所有属性类的config包中进行扫描,它也会全局启用配置属性。我用("com.my.config")注释了我的主类,并且最终找到了属性作为bean并自动装配,这是由于从这个位置进行了扫描。
小说明一下,DataSourcesConfiguration不会将自己注册为一个bean。但是最终它会被@ConfigurationProperties注释注册为一个bean。所以无论如何,@ConfigurationProperties注释的类都应该被注册为一个bean。