2014-10-01 50 views
26

È possibile avere campi (finali) immutabili con l'annotazione @ConfigurationProperties di Spring Boot? Esempio di sottoImmutable @ConfigurationProperties

@ConfigurationProperties(prefix = "example") 
public final class MyProps { 

    private final String neededProperty; 

    public MyProps(String neededProperty) { 
    this.neededProperty = neededProperty; 
    } 

    public String getNeededProperty() { .. } 
} 

Approcci ho provato finora:

  1. Creazione di un @Bean della classe MyProps con due costruttori
    • fornendo due costruttori: vuoti e con neededProperty argomento
    • Il bean è stato creato con new MyProps()
    • Risultati sul campo essendo null
  2. Utilizzando @ComponentScan e @Component per fornire il fagiolo MyProps.
    • Risultati in BeanInstantiationException ->NoSuchMethodException: MyProps.<init>()

L'unico modo che ho ottenuto che funziona è quello di fornire getter/setter per ogni campo non-finale.

+1

A mia conoscenza, quello che sei provare a fare non funzionerà fuori dalla scatola. – geoand

+0

Questo è triste.Ovviamente, posso sempre farlo con Spring semplice usando i parametri del costruttore con l'annotazione '@ Value'. Tuttavia, sarebbe bello se Spring Boot supportasse anche questo. – RJo

+0

Ho preso un piccolo picco nel codice sorgente, ma non è banale da sostenere qualcosa come quello che stai chiedendo. Naturalmente non sono un esperto di interni di Spring quindi potrei mancare qualcosa di ovvio – geoand

risposta

10

Devo risolvere il problema molto spesso e utilizzo un approccio leggermente diverso, che mi consente di utilizzare le variabili final in una classe.

Prima di tutto, mantengo tutta la mia configurazione in un unico posto (classe), ad esempio, chiamato ApplicationProperties. Questa classe ha l'annotazione @ConfigurationProperties con un prefisso specifico. È inoltre elencato nell'annotazione @EnableConfigurationProperties rispetto alla classe di configurazione (o alla classe principale).

Quindi fornire il mio ApplicationProperties come argomento del costruttore ed eseguire l'assegnazione a un campo final all'interno di un costruttore.

Esempio:

principale classe:

@SpringBootApplication 
@EnableConfigurationProperties(ApplicationProperties.class) 
public class Application { 
    public static void main(String... args) throws Exception { 
     SpringApplication.run(Application.class, args); 
    } 
} 

ApplicationProperties classe

@ConfigurationProperties(prefix = "myapp") 
public class ApplicationProperties { 

    private String someProperty; 

    // ... other properties and getters 

    public String getSomeProperty() { 
     return someProperty; 
    } 
} 

E una classe con proprietà finali

@Service 
public class SomeImplementation implements SomeInterface { 
    private final String someProperty; 

    @Autowired 
    public SomeImplementation(ApplicationProperties properties) { 
     this.someProperty = properties.getSomeProperty(); 
    } 

    // ... other methods/properties 
} 

Preferisco questo approccio per molti diversi motivi, ad es. se devo installare più proprietà in un costruttore, la mia lista di argomenti del costruttore non è "enorme" perché ho sempre un argomento (ApplicationProperties nel mio caso); se v'è la necessità di aggiungere altre final proprietà, il mio costruttore rimane lo stesso (solo un argomento) - che possono ridurre il numero di cambiamenti altrove ecc

Spero che vi aiuterà

+1

Questo è un gran numero di piastre di caldaia rispetto all'utilizzo di @Value –

+0

Questo è [tag: Java]. Più boilerplate significa codice migliore – Clijsters

+0

@Clijsters Onestamente non so dirti se sei un faceto, ma non è giusto, ma non è neanche lontanissimo! –