2017-01-10 4 views
0

Ich begann, Konstruktor-Injektion in meinen Projekten zu verwenden, seit Spring Feldinjektion als veraltet deklarierte. Eigentlich fühlt sich der Code hübscher und strenger an, damit bin ich einverstanden. Aber ich stieß auf ein Muster, das scheint ein bisschen ... seltsam und ausführliche mir:Spring-Konstruktor-Injektion und Super-Call-Ausführlichkeit

Ich habe eine abstrakte Service-Bean-Klasse (mit @Service Anmerkung), die, sagen wir 2 Abhängigkeiten hat, befindet sich direkt im Konstruktor injiziert:

Dann habe ich mehrere Dienste Bean-Klassen (immer noch mit @Service Annotation) die abstrakte Erweiterung. Und ich weiß nicht, ob es einen anderen Weg, aber das ist, wo ich ein bisschen ausführlicher und repetitive mit finden die Abhängigkeiten für die Eltern, die in jedem Unter Klassenkonstruktors zu injizieren:

@Service 
public class ServiceA extends AbstractService { 
    private final DepC depC; 

    @Autowired 
    public ServiceA(DepA depA, DepB depB, DepC depC) { 
     super(depA, depB); 
     this.depC = depC; 
    } 

} 

Ich wollte nur Wissen Sie, ob dies der richtige Weg ist und was Sie darüber denken?

+0

warum sollte es verbose oder reptitive sein. Ja, für Klassen mit nur einem möglichen Konstruktor könnte man so argumentieren, aber was wäre, wenn es in 'AbstractService' mehrere verschiedene überladene Konstruktoren gäbe, wie würde 'ServiceA' bestimmen, welches man aufrufen soll. Aber ja, das ist der richtige Weg. – SomeJavaGuy

+0

Das '@ Autowired' auf' AbstractService' tut nichts. – alexbt

+0

Ich kann nicht sehen, warum Sie abstrakten Konstruktor mit '@ Autowired' kommentieren müssen.Es wird nicht benötigt, da die Felder in den Superklassenkonstruktor eingefügt werden. Alles andere sieht gut aus. –

Antwort

2

Die @Autowired auf AbstractService macht nichts. Ändern Sie es in:

@Service 
public class ServiceA extends AbstractService { 
    private final DepC depC; 

    @Autowired 
    public ServiceA(DepA depA, DepB depB, DepC depC) { 
     super(depA, depB); 
     this.depC = depC; 
    } 
} 

... 

public AbstractService(DependencyA depA, DependencyB depB) { 
    this.depA = depA; 
    this.depB = depB; 
} 

Ich bin ok mit diesem Setup.

Für mich sind die Hauptvorteile der Verwendung von Konstruktorinjektion, den Entwickler zu informieren, was die externen Abhängigkeiten sind. Ich finde es nützlich beim Komponententest. Wenn du Mocks schreibst, weißt du nur, was man verspotten muss.

Ein anderer Vorteil ist zu markieren, wenn eine Klasse zu viele Abhängigkeiten hat, gibt es einen Hinweis, dass Refactoring in Ordnung sein kann.

Die Alternative würde Setter-Injektion verwenden (unter Beibehaltung der informativen Aspekt), aber ich habe zu genießen, Konstruktor Injektion zu genießen.

+0

Nun, ich stimme dir zu. Die Setter-Injektion wäre eine Lösung, aber ich bevorzuge die Konstruktorinjektion, da Felder "final" sein können. Und ich habe nie daran gedacht, die '@ Autowired'-Annotation aus dem Superklassenkonstruktor zu entfernen, aber es macht Sinn, jetzt sehe ich Ihren Code. – TheCypher

1

Meine Antwort konzentriert sich auf den "ausführlichen und wiederholenden" Teil in Ihrer Frage; Ich lasse andere entscheiden, wie "korrekt" Ihre Verwendung von Anmerkungen ist.

Auch mit Spring und seinem DI-Framework, am Ende sprechen wir noch über Java Quellcode!

Und in Java, wenn Ihre Basisklasse nur bietet einen Konstruktor, der einige A und B nimmt; dann natürlich Ihre Unterklasse hat einen Anruf Super (A a, B b); und natürlich müssen diese Werte a und b irgendwo herkommen!

Also, was Sie "ausführlich und repetitiv" nennen, ist eine direkte Konsequenz der Verwendung von Java.

Mit anderen Worten: Es gibt keine Möglichkeit, diesen Teil zu vermeiden!