Wie funktioniert @Required Annotation mit JavaConfig?

8

Ich bin ziemlich neu im Spring Framework und habe Probleme, die @Required -Anmerkung in Kombination mit einer Java-konfigurierten Anwendung zu verstehen.

Hier ist ein Beispiel.

Konfigurationsdatei

%Vor%

MovieHolder.java

%Vor%

Kontextinitialisierung

%Vor%

Soweit ich die Dokumentation der @Required Annotation verstanden habe, sollte eine Ausnahme auftreten, da der Film nicht direkt oder durch Autowiring gesetzt wird. Stattdessen ist die Ausgabe movie: null .

Was mache ich falsch? Oder ist das nicht die korrekte Verwendung der @Required Annotation?

    
a.ha 27.05.2013, 08:40
quelle

2 Antworten

8

Das Festlegen der erforderlichen Eigenschaften in den Beans, die Sie instanziieren, liegt in Ihrer eigenen Verantwortung. Die BeanPostProcessor , das die Bean-Definitionen in den mit @Configuration annotierten Klassen verarbeitet, heißt ConfigurationClassPostProcessor . Die BeanPostProcessor verarbeitet Ihre @Required -Anmerkungen standardmäßig auf RequiredAnnotationBeanPostProcessor , das standardmäßig registriert wird, wenn Sie context:annotation-config und context:component-scan in Ihrer Konfiguration verwenden. Wenn Sie diese beiden Tags nicht verwenden, können Sie sogar Ihre eigenen RequiredAnnotationBeanPostProcessor als bean .

Nun die Standardimplementierung von RequiredAnnotationBeanPostProcessor hat eine Methode namens boolean shouldSkip(..) , die nach einem booleschen Attribut namens SKIP_REQUIRED_CHECK_ATTRIBUTE . Der Wert dieses Attributs wird für jede Bean während der Nachbearbeitung von RequiredAnnotationBeanPostProcessor . Wenn% ce_de% zurückgegeben wird, wird die false Einschränkung erzwungen, andernfalls nicht.

Nun, @Required setze den Wert dieses Attributs auf ConfigurationClassPostProcessor , während ich die Bean-Definitionen aus den true -Klassen erstelle (ich nehme an, wenn Sie eine Bean definieren, Sie sollte sicherstellen, dass es die erforderlichen Eigenschaften hat). Daher wird @Configuration für solche Beans nicht erzwungen.

Nebenbei bemerkt, könnten Sie denken, dass wo @Required Attribut kommt von und wo es gesetzt ist: Es wird auf die Instanzen von SKIP_REQUIRED_CHECK_ATTRIBUTE , die von Spring intern für die Erstellung und Nachbearbeitung von Beans verwendet werden.

Wenn Sie die BeanDefinition -Einschränkungen wirklich erzwingen wollen, müssten Sie die @Required , überschreiben Sie die RequiredAnnotationBeanPostProcessor -Methode und registrieren Sie diese Klasse anstelle der Vorgabe boolean shouldSkip(..) . Und als Dokumentation für RequiredAnnotationBeanPostProcessor sagt:

  

Ein Standard RequiredAnnotationBeanPostProcessor wird von den XML-Tags "context: annotation-config" und "context: component-scan" registriert. Entfernen oder deaktivieren Sie die Standardanmerkungskonfiguration dort, wenn Sie eine benutzerdefinierte RequiredAnnotationBeanPostProcessor-Bean-Definition angeben möchten.

Eine andere Möglichkeit wäre, das Attribut RequiredAnnotationBeanPostProcessor in Ihrer initMethod Annotation zu verwenden. Das könnte Prüfungen durchführen, um zu sehen, dass die erforderlichen Eigenschaften tatsächlich gesetzt sind. Da dies jedoch eine code-basierte Konfiguration ist, können Sie diese @Bean -Methode auch selbst aufrufen.

Auch meiner Meinung nach hat es nicht viel Sinn, eine Menge Ärger zu machen, um Ihre eigenen init , wie die folgende Dokumentation sagt:

  

Bitte beachten Sie, dass eine 'init' -Methode möglicherweise noch implementiert werden muss (und immer noch wünschenswert sein kann), da alles, was diese Klasse tut, erzwingt, dass eine 'erforderliche' Eigenschaft tatsächlich mit einem Wert konfiguriert wurde. Es überprüft nichts anderes ...Insbesondere wird nicht überprüft, ob ein konfigurierter Wert nicht null ist.

Zusammengefasst: RequiredAnnotationBeanPostProcessor funktioniert standardmäßig nicht mit @Required -Klassen. Wenn Sie sicherstellen müssen, dass alle Ihre Eigenschaften festgelegt sind, können Sie es genauso gut selbst tun, wenn Sie die Bean in den @Configuration -Methoden erstellen (indem Sie eine @Bean -Methode aufrufen, die solche Validierungen durchführt, oder einfach die erforderliche Menge angeben) Eigenschaften selbst). Und wenn Sie wirklich die init -Anmerkung aktivieren müssen, müssen Sie Ihre eigene Implementierung von @Required , registriere es als eine Bohne im Frühling und gib die Vorteile von RequiredAnnotationBeanPostProcessor auf .

    
Bhashit Parikh 27.05.2013, 12:52
quelle
1

Ich habe gerade versucht, einen @Bean RequiredAnnotationBeanPostProcessor mit überschriebener shouldSkip () Methode zu deklarieren.

Ja, es prüft meine Beans, aber es schlägt fehl, selbst wenn ich alle erforderlichen Eigenschaften einstelle, d. h. es schlägt immer fehl.
Ich denke, Spring hat ein echtes Problem mit der Unterstützung der Annotation @Required für Java Config, da Spring nicht feststellen kann, ob Sie die Eigenschaft direkt in Java-Code gesetzt haben oder nicht. (Es kann später nicht nach 'Null'-Feldern suchen, da dies bedeuten würde, die Semantik der Annotation @Required zu ändern, die explizit festgelegte Nullwerte zulässt.)

Wenn Sie eine XML-Konfiguration verwenden, erstellt Spring ein Wrapper-Objekt zum Festlegen der Eigenschaften, sodass es alle konfigurierten 'setXxx ()' -Operationen verfolgen kann.

Schlussfolgerung : Es gibt keine vernünftige Möglichkeit, die @Required Annotation für in Java @Configuration Klassen erstellte Beans zu aktivieren.
(Sehr unglückliches Feature, meiner Meinung nach, da der Bean Class Writer und der Klassenbenutzer verschiedene Personen sein könnten).

    
Alexander 05.11.2014 12:42
quelle

Tags und Links