java - spring_application_json - spring properties file
Immutable @ConfigurationProperties (2)
Al final, si quieres un objeto inmutable también puedes "piratear" el setter que es
@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;
}
}
}
Obviamente, si la propiedad no es solo un String, es un objeto mutable, las cosas son más complicadas, pero esa es otra historia.
Aún mejor, puedes crear un contenedor de Configuración
@ConfigurationProperties(prefix = "myapp")
public class ApplicationProperties {
private final List<MyConfiguration> configurations = new ArrayList<>();
public List<MyConfiguration> getConfigurations() {
return configurations
}
}
donde ahora la configuración es un clas sin
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;
}
}
}
y application.yml como
myapp:
configurations:
- someProperty: one
- someProperty: two
- someProperty: other
¿Es posible tener campos inmutables (finales) con la anotación @ConfigurationProperties
Spring Boot? Ejemplo a continuación
@ConfigurationProperties(prefix = "example")
public final class MyProps {
private final String neededProperty;
public MyProps(String neededProperty) {
this.neededProperty = neededProperty;
}
public String getNeededProperty() { .. }
}
Enfoques que he intentado hasta ahora:
- Crear un
@Bean
de la claseMyProps
con dos constructores- Proporcionar dos constructores: vacío y con argumento de
neededProperty
- El bean se crea con
new MyProps()
- Resultados en el campo siendo
null
- Proporcionar dos constructores: vacío y con argumento de
- Usando
@ComponentScan
y@Component
para proporcionar el beanMyProps
.- Resultados en
BeanInstantiationException
->NoSuchMethodException: MyProps.<init>()
- Resultados en
La única forma en que lo tengo funcionando es proporcionando getter / setter para cada campo no final.
Tengo que resolver ese problema muy a menudo y utilizo un enfoque un poco diferente, que me permite usar variables final
en una clase.
En primer lugar, mantengo toda mi configuración en un solo lugar (clase), por ejemplo, llamado ApplicationProperties
. Esa clase tiene la anotación @ConfigurationProperties
con un prefijo específico. También aparece en la anotación @EnableConfigurationProperties
en la clase de configuración (o clase principal).
Luego proporciono mis ApplicationProperties
como un argumento constructor y realizo la asignación a un campo final
dentro de un constructor.
Ejemplo:
Clase principal :
@SpringBootApplication
@EnableConfigurationProperties(ApplicationProperties.class)
public class Application {
public static void main(String... args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Clase ApplicationProperties
@ConfigurationProperties(prefix = "myapp")
public class ApplicationProperties {
private String someProperty;
// ... other properties and getters
public String getSomeProperty() {
return someProperty;
}
}
Y una clase con propiedades finales
@Service
public class SomeImplementation implements SomeInterface {
private final String someProperty;
@Autowired
public SomeImplementation(ApplicationProperties properties) {
this.someProperty = properties.getSomeProperty();
}
// ... other methods / properties
}
Prefiero este enfoque por muchas razones diferentes, por ejemplo, si tengo que configurar más propiedades en un constructor, mi lista de argumentos de constructor no es "enorme" ya que siempre tengo un argumento ( ApplicationProperties
en mi caso); si hay una necesidad de agregar más propiedades final
, mi constructor permanece igual (solo un argumento) - eso puede reducir el número de cambios en otro lugar, etc.
Espero que le ayudará