wake-up-neo.net

Frühling @Autowired use

Was sind die Vor- und Nachteile der Verwendung von @Autowired in einer Klasse, die von Spring verkabelt wird? 

Zur Klarstellung, ich spreche speziell von der Annotation @Autowired , nicht von der automatischen Verkabelung in XML.

Ich verstehe es wahrscheinlich einfach nicht, aber es scheint mir fast ein Anti-Muster zu sein - Ihre Klassen werden sich bewusst, dass sie an ein DI-Framework gebunden sind und nicht nur POJOs sind. Vielleicht bin ich ein Vollfraß für Bestrafungen, aber ich mag die externe XML-Konfiguration für Beans und explizite Verdrahtungen, daher weiß ich genau, was wo verdrahtet ist.

207
Andy White

Lange Zeit war ich der Meinung, dass eine "zentralisierte, deklarative Konfiguration" wie die XML-Dateien, die wir alle verwendet haben, von Nutzen ist. Dann wurde mir klar, dass die meisten Dinge in den Dateien keine Konfiguration waren - sie wurden nach der Entwicklung nie mehr geändert. Dann wurde mir klar, dass "zentralisiert" nur in sehr kleinen Systemen von Nutzen ist - nur in kleinen Systemen können Sie eine Konfigurationsdatei als Ganzes erstellen. Und welchen Wert hat es wirklich, die Verkabelung als Ganzes zu verstehen, wenn dieselben "Verkabelungen" zumeist durch Abhängigkeiten im Code dupliziert werden? Das einzige, was ich behalten habe, sind Metadaten (Anmerkungen), die immer noch deklarativ sind. Diese nie ändern sich zur Laufzeit und sie sind nie "Konfigurationsdaten", die jemand im laufenden Betrieb ändern wird - also denke ich, sie bleiben im Code ist schön.

Ich benutze so oft ich kann die volle Autoverkabelung. Ich liebe es. Ich werde nicht zum alten Frühling zurückkehren, wenn ich nicht mit vorgehaltener Waffe bedroht werde. Meine Gründe für die Bevorzugung von @Autowired haben sich im Laufe der Zeit geändert.

Momentan denke ich, dass der wichtigste Grund für die Verwendung von Autowiring darin besteht, dass in Ihrem System eine Abstraktion weniger vorhanden ist, um den Überblick zu behalten. Der "Bohnenname" ist praktisch weg. Es stellt sich heraus, dass der Bean-Name nur aufgrund von XML existiert. So ist eine ganze Ebene abstrakter Indirektionen (wo Sie den Bohnennamen "foo" in die Bohnen "bar" verdrahten würden) verschwunden. Jetzt verbinde ich die "Foo" -Schnittstelle direkt mit meinem Bean, und die Implementierung wird durch das Laufzeitprofil ausgewählt. Auf diese Weise kann ich mit Code arbeiten, wenn ich Abhängigkeiten und Implementierungen nachverfolge. Wenn ich in meinem Code eine automatisch verdrahtete Abhängigkeit sehe, kann ich einfach die Taste "Gehe zur Implementierung" in meinem IDE drücken und die Liste der bekannten Implementierungen wird angezeigt. In den meisten Fällen gibt es nur eine Implementierung und ich bin direkt in der Klasse. Einfacher kann es nicht sein, und ich weiß immer genau , welche Implementierung verwendet wird (ich behaupte, dass das Gegenteil bei der XML-Verkabelung der Wahrheit näher ist - lustig, wie sich Ihre Perspektive ändert! )

Nun könnte man sagen, dass es sich nur um eine sehr einfache Ebene handelt, aber jede Abstraktionsebene, die wir unseren Systemen hinzufügen , erhöht die Komplexität. Ich glaube wirklich nicht, dass die XML jemals einen echten Mehrwert für ein System gebracht hat, mit dem ich gearbeitet habe.

Die meisten Systeme, mit denen ich jemals gearbeitet habe, haben nur eine Konfiguration der Produktionslaufzeitumgebung. Möglicherweise gibt es andere Konfigurationen für den Test und so weiter.

Ich würde sagen, dass die vollständige automatische Verdrahtung das Ruby-on-Rails-Prinzip des Frühlings ist: Es schließt die Vorstellung ein, dass es ein normales und allgemeines Verwendungsmuster gibt, dem die meisten Anwendungsfälle folgen. Mit der XML-Konfiguration erlauben Sie eine Menge konsistenter/inkonsistenter Konfigurationsverwendungen, die möglicherweise nicht beabsichtigt sind. Ich habe gesehen, dass so viele XML-Konfigurationen mit Inkonsistenzen überfrachtet wurden. Wird sie zusammen mit dem Code überarbeitet? Dachte nicht. Gibt es diese Variationen aus einem Grund? Normalerweise nicht.

Wir verwenden in unserer Konfiguration kaum Qualifikationsmerkmale und haben andere Wege gefunden, um diese Situationen zu lösen. Dies ist ein klarer "Nachteil", auf den wir stoßen: Wir haben die Art und Weise, in der wir Code verwenden, leicht geändert, um die Interaktion mit Autowiring zu vereinfachen: Ein Kundenrepository implementiert nicht mehr die generische Repository<Customer> -Schnittstelle, sondern wir erstellen eine Schnittstelle CustomerRepository das erweitert Repository<Customer>. Manchmal gibt es auch ein oder zwei Tricks, wenn es um Unterklassen geht. Aber es zeigt uns normalerweise nur in die Richtung einer stärkeren Typisierung, was ich fast immer als bessere Lösung empfinde.

Aber ja, Sie sind an einen bestimmten DI-Stil gebunden, den der Frühling meistens hat. Wir veröffentlichen nicht einmal mehr öffentliche Setter für Abhängigkeiten (Sie könnten also behaupten, dass wir +1 in der Abteilung zum Verbergen von Informationen/Kapseln haben). Wir haben immer noch einige XML-Dateien in unserem System, aber die XML-Dateien im Grunde genommen nur enthält die Anomalien. Vollständiges Autowiring lässt sich gut in XML integrieren.

Das einzige, was wir jetzt brauchen, ist, dass @Component, @Autowired und der Rest in einem JSR enthalten sind (wie JSR-25 ), also müssen wir nicht mit dem Frühling binden. Dies ist die Art und Weise, wie die Dinge in der Vergangenheit geschehen sind (das Java.util.concurrent -Ding kommt mir in den Sinn), daher wäre ich nicht völlig überrascht, wenn dies erneut geschehen würde.

249
krosenvold

Für mich ist das, was ich an Spring und Auto-Verkabelung mag/nicht mag.

Pros:

  • Durch die automatische Verkabelung wird die unangenehme XML-Konfiguration entfernt.
  • Die Verwendung von Annotationen ist viel einfacher, sodass Sie mit Feldern, Setter-Methoden oder Konstruktoren direkt injizieren können. Außerdem können Sie Ihre injizierten Beans mit Anmerkungen versehen und "qualifizieren".

Nachteile:

  • Durch die automatische Verdrahtung und Anmerkungen werden Sie von Spring-Bibliotheken abhängig, bei denen Sie sich wie bei der XML-Konfiguration für die Ausführung mit oder ohne Spring entscheiden könnten. Wie Sie gesagt haben, sind Sie an ein DI-Framework gebunden.
  • Zur gleichen Zeit mag ich es, Beans zu "qualifizieren", für mich macht dies den Code wirklich unordentlich. Wenn Sie dieselbe Bean an mehreren Stellen injizieren müssen, habe ich den gleichen String-Namen überall wiederholt. Mir scheint das Fehlerpotenzial zu haben.

Ich arbeite fast ausschließlich mit der automatischen Verkabelung, weil wir sowieso so sehr auf die Spring-Integration angewiesen sind, dass das Abhängigkeitsproblem moot ist. Ich habe an einem Spring-MVC-Projekt gearbeitet, bei dem die Auto-Verkabelung ausgiebig verwendet wurde und es ein wenig schwer war, meinen Kopf herumzuschlagen.

Ich denke, die automatische Verkabelung ist ein erworbener Geschmack. Wenn Sie sich erst einmal daran gewöhnt haben, erkennen Sie, wie mächtig, einfach und viel weniger Kopfschmerzen die Arbeit mit der XML-Konfiguration macht.

26
Jared Knipp

In unserem großen Projekt wechseln wir von @Autowire zurück zur XML-Konfiguration. Das Problem ist eine sehr geringe Bootstrap-Leistung. Der Scanner für automatische Einstellung lädt alle Klassen aus dem Suchpfad der automatischen Suche, sodass viele Klassen während der Spring-Initialisierung mit Spannung geladen werden.

15
Masterhard

Es wurde sehr wenig über das Wechseln der Umgebung diskutiert. Die meisten Projekte, an denen ich gearbeitet habe, waren ein echtes Problem, um Abhängigkeiten abhängig von der Umgebung, in der wir arbeiten, einzuführen. Mit xml config ist es mit Spring EL ziemlich unkompliziert, und ich kenne keine Nice-Lösung mit Anmerkungen. Ich habe gerade einen herausgefunden:

    @Value("#{${env} == "production" ? realService : dummyService}")
    private SomeService service;

Es sollte funktionieren, aber keine schöne Lösung imho.

6
BTakacs

Ich habe zu @Autowire gewechselt. Das Beibehalten der XML-Konfiguration für ein anderes als ein kleines Projekt wurde zu einer eigenständigen Aufgabe, und das Verständnis wurde schnell beeinträchtigt. 

IntelliJ bietet eine gute (nicht perfekte) Unterstützung für Spring-Anmerkungen.

4
Paul McKenzie

Meine Meinung zu diesem Thema ist, dass die XML-Konfiguration die Klarheit des Codes verringert, insbesondere in großen Systemen. 

Anmerkungen wie @Component machen die Sache noch schlimmer. Er steuert Entwickler, Objekte veränderbar zu machen, da Abhängigkeiten nicht mehr endgültig gemacht werden können, da Standardkonstruktoren bereitgestellt werden müssen. Abhängigkeiten müssen entweder über einen öffentlichen Setter eingefügt oder über @Autowired unkontrolliert werden. [Noch schlimmer ist die Abhängigkeitsinjektion durch Klassen, die ihre Abhängigkeiten instanziieren, ich sehe das immer noch in neu geschriebenem Code!]. Mit unkontrolliert meine ich, in großen Systemen, wenn mehrere Implementierungen (oder untergeordnete Elemente) dieses Typs verfügbar sind, wird es umso schwieriger zu verstehen, welche der Implementierungen @Autowired war. Es bedeutet auch, dass Sie angeblich ein Profil für die Testumgebung und ein anderes für die Produktion haben. Ihre Produktionsfehler treten nur dann auf, wenn es am meisten schmerzt - in der Produktion, anstatt die Fehler in der Testumgebung oder noch besser bei Zeit kompilieren!

Ich bleibe auf dem Mittelweg, wo ich meine Konfigurationsklasse (n) deklariere (Java-basierte Spring-Konfiguration mit @Configuration).

Ich erkläre alle meine Beans explizit in den Konfigurationsklassen. Ich verwende nur @Autowired in den Konfigurationsklassen. Der Zweck besteht darin, die Abhängigkeit von Spring auf die Konfigurationsklassen zu begrenzen.

Die @Configuration befindet sich in einem bestimmten Paket. Nur hier wird der Frühjahrsscan ausgeführt. (Das beschleunigt die Startzeit bei großen Projekten erheblich)

Ich bemühe mich, alle meine Klassen unveränderlich zu machen, insbesondere die Datenobjekte JPA, Hibernate und Spring sowie viele Serialisierungsbibliotheken scheinen dies zu unterminieren. Ich entferne mich von allem, was mich dazu zwingt, Setter bereitzustellen, oder das letzte Schlüsselwort aus meiner Eigentumserklärung entfernen.

Durch die Reduzierung der Änderungsmöglichkeiten von Objekten nach ihrer Erstellung werden die Fehler in großen Systemen erheblich reduziert. Außerdem wird die Zeit zum Suchen eines Fehlers verringert, wenn ein Fehler vorliegt. 

Es scheint auch, dass der Entwickler gezwungen wird, die Interaktion zwischen den verschiedenen Teilen des Systems besser zu gestalten. Probleme und Fehler werden immer mehr zu Kompilierungsfehlern, wodurch Zeitverschwendung reduziert und die Produktivität verbessert wird.

3
Charbel

Ich liebe es, mit Anmerkungen zu schreiben, anstatt mit XML . Gemäß dem Spring-Handbuch und den letzten Versionen erzielten XML und Annotation dasselbe Ergebnis.

Das ist meine Liste

Profi:

  • Entfernen Sie unbrauchbare Zeilen aus XML
  • Vereinfachen Sie das Debuggen des Codes: Wenn Sie eine Klasse öffnen, können Sie lesen, was Sie in der Klasse haben 
  • Schnelleres Entwickeln, ein Projekt mit 400 oder mehr XML-Zeilen ist lesbar?

Nachteile:

  • Ist keine Standard-Java-Implementierung, Sie können jedoch zur Verwendung von @Inject wechseln, einer Java-Standard-Api, sodass die Bean ein Pojo bleibt
  • Sie können nicht einfach überall, db connection usw. verwenden, aber es ist nur eine Meinung, ich bevorzuge einen Ort, an dem alle Konfigurationen gelesen werden können. 
1
Luca Preziati

Hier sind einige Erfahrungen 
Vorteile  

  • Einfacher zu konfigurieren, da wir einfach die @Autowire-Annotation verwenden können
  • Ich möchte keine Setter-Methoden verwenden, damit die Klasse sauberer wird

Nachteile

  • Koppeln Sie eng an die XML-Datei, obwohl wir DI verwenden
  • Schwer zu findende Implementierung (aber wenn Sie gute Ides wie Intellij verwenden, können Sie diese einfach loswerden)

Bei meinen persönlichen Erfahrungen habe ich die @AutoWire-Annotation nur in Testfällen verwendet. 

1
Rajith Delantha

Für mein Verständnis ist @Autowired am besten zu verwenden, während auf die Schnittstellenreferenz verwiesen wird und seine Überschreibungsfunktionen verwendet werden, aber ich finde nur das Problem, dass es manchmal zur Laufzeit null zugewiesen wird.

0
Shubham kapoor