不可变的@ConfigurationProperties
是否可以使用Spring Boot的@ConfigurationProperties
注释创建不可变(最终)字段? 以下示例
@ConfigurationProperties(prefix = "example") public final class MyProps { private final String neededProperty; public MyProps(String neededProperty) { this.neededProperty = neededProperty; } public String getNeededProperty() { .. } }
到目前为止我尝试过的方法:
- 使用两个构造函数创建
MyProps
类的MyProps
- 提供两个构造函数:empty和
neededProperty
参数 - 使用
new MyProps()
创建bean - 该字段的结果为
null
- 提供两个构造函数:empty和
- 使用
@ComponentScan
和@Component
提供MyProps
bean。-
BeanInstantiationException
结果 – >NoSuchMethodException: MyProps.()
-
我得到它的唯一方法是为每个非最终字段提供getter / setter。
我必须经常解决这个问题,并且我使用了一种不同的方法,这允许我在类中使用final
变量。
首先,我将所有配置保存在一个地方(类),比如称为ApplicationProperties
。 该类具有带有特定前缀的@ConfigurationProperties
注释。 它还在针对配置类(或主类)的@EnableConfigurationProperties
注释中列出。
然后我将我的ApplicationProperties
作为构造函数参数提供,并对构造函数中的final
字段执行赋值。
例:
主要课程:
@SpringBootApplication @EnableConfigurationProperties(ApplicationProperties.class) public class Application { public static void main(String... args) throws Exception { SpringApplication.run(Application.class, args); } }
ApplicationProperties
类
@ConfigurationProperties(prefix = "myapp") public class ApplicationProperties { private String someProperty; // ... other properties and getters public String getSomeProperty() { return someProperty; } }
还有一个具有最终属性的类
@Service public class SomeImplementation implements SomeInterface { private final String someProperty; @Autowired public SomeImplementation(ApplicationProperties properties) { this.someProperty = properties.getSomeProperty(); } // ... other methods / properties }
我更喜欢这种方法有很多不同的原因,例如,如果我必须在构造函数中设置更多属性,我的构造函数参数列表不是“巨大”,因为我总是有一个参数(在我的例子中是ApplicationProperties
); 如果需要添加更多的final
属性,我的构造函数保持不变(只有一个参数) – 这可能会减少其他地方的更改次数等。
我希望这会有所帮助
最后,如果你想要一个不可变对象,你也可以“破解”那个setter
@ConfigurationProperties(prefix = "myapp") public class ApplicationProperties { private String someProperty; // ... other properties and getters public String getSomeProperty() { return someProperty; } public String setSomeProperty(String someProperty) { if (someProperty == null) { this.someProperty = someProperty; } } }
显然,如果属性不仅仅是一个String,那是一个可变对象,事情就更复杂了,但这是另一个故事。
更好的是,您可以创建配置容器
@ConfigurationProperties(prefix = "myapp") public class ApplicationProperties { private final List configurations = new ArrayList<>(); public List getConfigurations() { return configurations } }
现在配置是没有的clas
public class MyConfiguration { private String someProperty; // ... other properties and getters public String getSomeProperty() { return someProperty; } public String setSomeProperty(String someProperty) { if (someProperty == null) { this.someProperty = someProperty; } } }
和application.yml as
myapp: configurations: - someProperty: one - someProperty: two - someProperty: other