Spring @Autowired Verwendung

218

Was sind die Vor- und Nachteile der Verwendung von @Autowired in einer Klasse, die bis zum Frühjahr verkabelt sein wird?

Zur Verdeutlichung spreche ich speziell über die Annotation @Autowired und nicht über die automatische Verkabelung in XML.

Ich verstehe es wahrscheinlich einfach nicht, aber für mich scheint es fast wie ein Anti-Muster - Ihre Klassen werden sich bewusst, dass sie an ein DI-Framework gebunden sind, anstatt nur POJOs zu sein. Vielleicht bin ich ein Vielfraß bei der Bestrafung, aber ich mag es, die externe XML-Konfiguration für Beans zu haben, und ich mag explizite Verkabelungen, damit ich genau weiß, was wo verkabelt ist.

Andy White
quelle
4
Ich interessiere mich auch für dieses Thema - die Konfiguration Ihrer MVC-App über Anmerkungen anstelle von XML scheint zu einer häufigen Suche nach "Welche Klasse ist dieser URL zugeordnet?" Zu führen. "Wer kümmert sich darum?". Ich möchte eine einzige Konfigurationsquelle haben
matt b
6
Der Begriff "@Autowiring" scheint hier irreführend zu sein. Da Sie die XML-Konfiguration auch automatisch verdrahten können, sollte die ursprüngliche Frage als "Vor- und Nachteile der Verwendung von Spring-Anmerkungen" umformuliert werden. Die bereitgestellte Antwort konzentriert sich mehr auf die Aspekte der automatischen Verdrahtung und weniger auf Aspekte der Verwendung von Anmerkungen.
Neeme Praks
Mögliches Duplikat von Understanding Spring @Autowired
tkruse

Antworten:

253

Lange Zeit glaubte ich, dass eine "zentralisierte, deklarative Konfiguration" wie die XML-Dateien, die wir alle verwendet haben, einen Wert hat. Dann wurde mir klar, dass die meisten Inhalte in den Dateien keine Konfiguration waren - sie wurden nach der Entwicklung nie geändert. Dann wurde mir klar, dass "zentralisiert" nur in recht kleinen Systemen einen Wert hat - nur in kleinen Systemen können Sie jemals eine Konfigurationsdatei als Ganzes erstellen . Und was ist es wirklich wert, die Verkabelung als Ganzes zu verstehen, wenn dieselben "Verkabelungen" meist durch Abhängigkeiten im Code dupliziert werden? Das einzige, was ich behalten habe, sind Metadaten (Anmerkungen), die immer noch deklarativ sind. Diese ändern sich nie zur Laufzeit und sie sind nie "Konfigurations" -Daten, die jemand im laufenden Betrieb ändern wird - daher finde ich es schön, sie im Code zu behalten.

Ich verwende so oft ich kann eine vollautomatische Verkabelung. Ich liebe es. Ich werde nicht zum alten Frühling zurückkehren, wenn ich nicht mit vorgehaltener Waffe bedroht bin. Meine Gründe für den Vorzug @Autowiredhaben sich im Laufe der Zeit geändert.

Im Moment denke ich, dass der wichtigste Grund für die Verwendung von Autowiring darin besteht, dass es in Ihrem System eine Abstraktion weniger gibt, die Sie im Auge behalten müssen. Der "Bohnenname" ist praktisch weg. Es stellt sich heraus, dass der Bean-Name nur aufgrund von XML existiert. Eine vollständige Schicht abstrakter Indirektionen (bei denen Sie den Bohnennamen "foo" in die Bohnenleiste "bar" verdrahten würden) ist also verschwunden. Jetzt verdrahte ich die "Foo" -Schnittstelle direkt mit meiner Bean, und die Implementierung wird durch das Laufzeitprofil ausgewählt. Dadurch kann ich beim Nachverfolgen von Abhängigkeiten und Implementierungen mit Code arbeiten . Wenn ich eine automatisch verdrahtete Abhängigkeit in meinem Code sehe, kann ich einfach die Taste "Zur Implementierung gehen" in meiner 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. Können' Welche Implementierung wird verwendet? (Ich behaupte, dass das Gegenteil mit XML-Verkabelung der Wahrheit näher kommt - lustig, wie sich Ihre Perspektive ändert!)

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

Die meisten Systeme, mit denen ich jemals gearbeitet habe, haben nur eine Konfiguration der Produktionslaufzeitumgebung. Möglicherweise gibt es andere Konfigurationen zum Testen und so weiter.

Ich würde sagen, dass volles Autowiring der Rubin auf Schienen des Frühlings ist: Es umfasst die Vorstellung, 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 über Bord gehen - 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“ wir begegnen: Wir leicht die Art , wie wir Code geändert haben damit interact glatter zu machen autowiring: Ein Kunde Repository nicht mehr implementiert die generische Repository<Customer>Schnittstelle , aber wir machen eine Schnittstelle , CustomerRepositorydie erweitert Repository<Customer>. Manchmal gibt es auch ein oder zwei Tricks, wenn es um Unterklassen geht. Aber es weist uns normalerweise nur in Richtung einer stärkeren Eingabe, was meiner Meinung nach fast immer eine bessere Lösung ist.

Aber ja, Sie binden an einen bestimmten DI-Stil, den der Frühling meistens tut. Wir machen nicht einmal mehr öffentliche Setter für Abhängigkeiten (Sie könnten also argumentieren, dass wir in der Abteilung für Kapselung / Verstecken von Informationen +1 sind). Wir haben immer noch einige XML-Dateien in unserem System, aber die XML-Dateien enthalten im Grunde nur die Anomalien. Full Autowiring lässt sich gut in XML integrieren.

Das einzige, was wir jetzt brauchen, ist @Component, dass @Autowiredder Rest in einem JSR (wie JSR-250 ) enthalten ist, damit wir uns nicht an den Frühling binden müssen. Dies ist die Art und Weise, wie die Dinge in der Vergangenheit passiert sind (das java.util.concurrentZeug fällt mir ein), daher wäre ich nicht ganz überrascht, wenn dies erneut passieren würde.

Krosenvold
quelle
5
Das javax.annotation / javax.inject wird von spring unterstützt, sodass Sie nicht die Code-Abhängigkeit von Spring haben müssen.
Michael Wiles
26

Für mich ist hier, was ich an Feder und automatischer Verkabelung mag / nicht mag.

Vorteile:

  • Durch die automatische Verkabelung wird die unangenehme XML-Konfiguration beseitigt.
  • Es ist viel einfacher, Anmerkungen zu verwenden, mit denen Sie Felder, Setter-Methoden oder Konstruktoren direkt einfügen können. Außerdem können Sie Ihre injizierten Bohnen mit Anmerkungen versehen und "qualifizieren".

Nachteile:

  • Durch die automatische Verkabelung und Anmerkungen sind Sie von Spring-Bibliotheken abhängig, bei denen Sie wie bei der XML-Konfiguration wählen können, ob Sie mit oder ohne Spring ausgeführt werden möchten. Wie Sie sagten, werden Sie an ein DI-Framework gebunden.
  • Gleichzeitig mag ich es, Bohnen "qualifizieren" zu können, was den Code für mich wirklich chaotisch macht. Wenn Sie dieselbe Bohne an mehreren Stellen injizieren müssen, wurde derselbe Zeichenfolgenname überall wiederholt. Für mich scheint dies das Potenzial für Fehler zu haben.

Ich habe angefangen, die automatische Verkabelung fast ausschließlich bei der Arbeit zu verwenden, da wir sowieso so stark von der Spring-Integration abhängen, dass das Abhängigkeitsproblem strittig ist. Ich habe an einem Spring MVC-Projekt gearbeitet, bei dem die automatische Verkabelung ausgiebig verwendet wurde und es etwas schwierig war, meinen Kopf herumzuwickeln.

Ich denke, Auto-Wiring ist ein erworbener Geschmack. Wenn Sie sich erst einmal daran gewöhnt haben, werden Sie feststellen, wie leistungsfähig, einfach und viel weniger Kopfschmerzen es mit sich bringt als mit der XML-Konfiguration.

Jared Knipp
quelle
3
XML-Konfiguration wird viel weniger unangenehm, wenn Sie die kostenlose Springsource Tool Suite verwenden, die Autovervollständigung, Bean-Diagramme usw. bietet
Sean Patrick Floyd
Ich stimme Ihnen voll und ganz zu, dass die automatische Verkabelung unordentlich und abhängig von den Federbibliotheken wird! Ich habe die XML-Konfiguration noch nie verwendet und denke, ich sollte diesen Weg vielleicht gehen?
James111
15

In unserem großen Projekt wechseln wir von @Autowire zurück zur XML-Konfiguration. Das Problem ist die sehr geringe Bootstrap-Leistung. Der Autowiring-Scanner lädt alle Klassen aus dem Autowiring-Suchklassenpfad, sodass viele Klassen während der Spring-Initialisierung eifrig geladen werden.

Masterhard
quelle
1
Ich habe festgestellt, dass javaconfig sogar eine bessere Lösung für das Starten von Teilkontexten ist, was ein großer Gewinn ist. Sie können diese jedoch ganz einfach kombinieren, indem Sie @ Autowired / @ Inject für Konstruktoren verwenden (mit anderen Worten, wechseln Sie zur Konstruktorinjektion).
Krosenvold
6

Über Switching-Umgebungen wurde bisher kaum diskutiert. Die meisten Projekte, an denen ich gearbeitet habe, waren ein echtes Problem, Abhängigkeiten abhängig von der Umgebung, an der wir arbeiten, einzufügen. Mit der XML-Konfiguration ist es mit Spring EL ziemlich einfach, und mir ist keine gute Lösung mit Anmerkungen bekannt. Ich habe gerade eines herausgefunden:

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

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

BTakacs
quelle
Ich habe einen separaten Thread dazu geöffnet, und es gibt eine Lösung mit Spring @Profilesund @Configuration: blog.springsource.org/2011/02/14/… Siehe auch den anderen Thread: stackoverflow.com/questions/13490393/…
BTakacs
4

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

IntelliJ bietet eine gute (nicht perfekte) Unterstützung für Frühlingsanmerkungen.

Paul McKenzie
quelle
3

Ich gehe davon aus, dass die XML-Konfiguration die Klarheit des Codes verringert, insbesondere in großen Systemen.

Anmerkungen wie @Component machen die Sache noch schlimmer. Entwickler werden angewiesen, Objekte veränderbar zu machen, da Abhängigkeiten nicht mehr endgültig festgelegt werden können, da Standardkonstruktoren bereitgestellt werden müssen. Abhängigkeiten müssen entweder über einen öffentlichen Setter oder über @Autowired unkontrolliert injiziert werden. [Noch schlimmer ist, dass die Abhängigkeitsinjektion durch Klassen beeinträchtigt wird, die ihre Abhängigkeiten instanziieren. Ich sehe dies immer noch in neu geschriebenem Code!]. Mit unkontrolliert meine ich, dass in großen Systemen, wenn mehrere Implementierungen (oder untergeordnete Elemente) des Typs verfügbar sind, es viel komplizierter wird zu verstehen, welche der Implementierungen @Autowired war, eine Komplexität, die die Untersuchung von Fehlern viel schwieriger macht. Es bedeutet auch, dass Sie angeblich ein Profil für die Testumgebung und ein anderes für die Produktion haben.

Ich halte mich an den Mittelweg, auf dem ich meine Konfigurationsklasse (n) deklariere (Java-basierte Spring-Konfiguration mit @Configuration).

Ich deklariere alle meine Beans explizit in den Konfigurationsklassen. Ich verwende @Autowired nur in den Konfigurationsklassen. Der Zweck besteht darin, die Abhängigkeit von Spring auf die Konfigurationsklasse (n) zu beschränken.

Die @Configuration befindet sich in einem bestimmten Paket. Dies ist der einzige Ort, an dem der Frühlingsscan ausgeführt wird. (Das beschleunigt die Startzeit bei großen Projekten erheblich.)

Ich bemühe mich, alle meine Klassen unveränderlich zu machen, insbesondere das Datenobjekt, JPA, Hibernate und Spring, sowie viele Serialisierungsbibliotheken scheinen dies zu untergraben. Ich meide alles, was mich zwingt, Setter bereitzustellen, oder entferne das letzte Schlüsselwort aus meiner Eigenschaftsdeklaration.

Durch das Reduzieren der Möglichkeiten zum Ändern von Objekten nach ihrer Erstellung werden die Fehler in großen Systemen erheblich reduziert und die Zeit zum Auffinden eines Fehlers, falls vorhanden, verkürzt.

Es scheint auch, dass es den Entwickler zwingt, die Interaktion zwischen den verschiedenen Teilen des Systems besser zu gestalten. Probleme und Fehler werden zu immer mehr Kompilierungsfehlern, die Zeitverschwendung reduzieren und die Produktivität verbessern.

Charbel
quelle
1

Hier sind einige erfahrene
Profis

  • Erleichtert die Konfiguration, da wir nur die @ Autowire-Annotation verwenden können
  • Sie möchten keine Setter-Methoden verwenden, damit die Klasse sauberer wird

Nachteile

  • Eng an die XML-Datei koppeln, obwohl wir DI verwenden
  • Schwer zu findende Implementierung (Aber wenn Sie gute IDs wie Intellij verwenden, können Sie dies sicher loswerden)

Aufgrund meiner persönlichen Erfahrungen habe ich die @ AutoWire-Annotation nicht so oft verwendet, sondern in Testfällen.

Rajith Delantha
quelle
1

Ich liebe es wirklich, mit Anmerkungen anstelle von XML zu schreiben. Laut dem Spring-Handbuch und den letzten Versionen haben XML und Annotation das gleiche Ergebnis erzielt.

Das ist meine Liste

Profi:

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

Nachteile:

  • Ist keine Standard-Java-Implementierung, aber Sie können zu @Inject wechseln, einer Java-Standard-API, sodass die Bean ein Pojo bleibt
  • Sie können nicht einfach überall verwenden, DB-Verbindung usw., aber es ist nur eine Meinung, ich bevorzuge einen Ort, an dem alle Konfigurationen gelesen werden.
Luca Preziati
quelle
0

Nach meinem Verständnis ist @Autowired am besten zu verwenden, wenn Sie auf die Schnittstellenreferenz verweisen und deren Überschreibungsfunktionen verwenden. Ich habe jedoch nur das Problem, dass es zur Laufzeit manchmal null zugewiesen wird.

Shubham Kapoor
quelle