2014-10-01 4 views
26

Ist es möglich, unveränderliche (endgültige) Felder mit Spring Booths @ConfigurationProperties Annotation zu haben? Beispiel untenImmutable @ConfigurationProperties

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

    private final String neededProperty; 

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

    public String getNeededProperty() { .. } 
} 

Ansätze habe ich bisher versucht:

  1. eine @Bean der MyProps Klasse Erstellen mit zwei Konstrukteuren
    • zwei Konstrukteurs Providing: leer und mit neededProperty Argument
    • Die Bean wird erstellt mit new MyProps()
    • Ergebnisse im Bereich sein null
  2. Mit @ComponentScan und @Component die MyProps Bohne zur Verfügung zu stellen.
    • Ergebnisse in BeanInstantiationException ->NoSuchMethodException: MyProps.<init>()

Der einzige Weg, ich habe habe es funktioniert, indem Sie für jedes nicht-Endfeld Getter/Setter bereitstellt.

+1

Mein Wissen helfen, was du bist zu versuchen, wird nicht aus der Box funktionieren. – geoand

+0

Das ist traurig.Natürlich kann ich das immer mit einfachem Spring machen, indem ich Konstruktor-Parameter mit '@ Value' Annotation verwende. Es wäre jedoch schön, wenn Spring Boot dies auch unterstützen würde. – RJo

+0

Ich habe einen kleinen Blick auf den Quellcode genommen, aber es scheint nicht-trivial zu sein, etwas zu unterstützen, was Sie fragen. Natürlich bin ich kein Experte für Spring Internals, also könnte mir etwas offensichtlich fehlen – geoand

Antwort

10

Ich muss dieses Problem sehr oft lösen, und ich benutze einen etwas anderen Ansatz, der es mir erlaubt final Variablen in einer Klasse zu verwenden.

Zunächst einmal habe ich alle meine Konfiguration an einem einzigen Ort (Klasse), sagen wir, ApplicationProperties. Diese Klasse hat @ConfigurationProperties Annotation mit einem spezifischen Präfix. Es ist auch in @EnableConfigurationProperties Annotation gegen Konfigurationsklasse (oder Hauptklasse) aufgeführt.

Dann stelle ich meine ApplicationProperties als Konstruktor Argument und führen die Zuweisung zu einem final Feld innerhalb eines Konstruktors.

Beispiel:

Haupt Klasse:

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

ApplicationProperties Klasse

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

    private String someProperty; 

    // ... other properties and getters 

    public String getSomeProperty() { 
     return someProperty; 
    } 
} 

Und eine Klasse mit Endeigenschaften

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

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

    // ... other methods/properties 
} 

Ich bevorzuge diesen Ansatz aus vielen verschiedenen Gründen, z.B. Wenn ich mehr Eigenschaften in einem Konstruktor einrichten muss, ist meine Liste der Konstruktorargumente nicht "riesig", da ich immer ein Argument habe (ApplicationProperties in meinem Fall); wenn es eine Notwendigkeit mehr final Eigenschaften ist hinzuzufügen, bleibt mein Konstruktor das gleiche (nur ein Argument) -, die Anzahl der Änderungen reduzieren kann an andere Stelle usw.

Ich hoffe, dass

+1

Das ist eine Menge Kesselplatte im Gegensatz zu nur mit @Value –

+0

Dies ist [Tag: Java]. Mehr Boilerplate bedeutet besser Code – Clijsters

+0

@ Clijsters Ich kann ehrlich gesagt nicht sagen, ob Sie scherzhaft sind, aber ich meine, es ist nicht ganz richtig, aber es ist nicht weit davon entfernt! –