2009-03-09 7 views
14

Ausgehend von einem C++ Hintergrund muss ich die Komplexität der Java Welt und ihre Frameworks beherrschen. Mit Blick auf den Frühling Rahmen für DI bin ich finden es schwer zu glauben, dass ich jede Setter-Funktion machen müssen, die Gegenstand für DI Öffentlichkeit sein wird. Stört diese Anforderung nicht das Prinzip der Informationsverbergung?Wird die Abhängigkeitsinjektion von Spring Information nicht ausgeblendet?

Natürlich möchte ich Frühling in der Lage, einige private Teile meiner Klassen zu setzen, aber ich will sicherlich nicht jede Client-Klasse das gleiche tun können.

Was fehlt mir hier?

Antwort

6

Wenn Sie Code zu Schnittstellen, müssen Sie nur Setter auf den Implementierungen verfügbar machen. Wenn Sie die Schnittstellen in andere Teile des Systems injizieren, können sie nicht auf die Implementierungsdetails oder den Status der Objekte zugreifen.

+1

Diese Antwort impliziert, dass "coding to interfaces" bedeutet, dass jede Klasse eine separate Schnittstelle implementieren muss. Dies ist nicht, was das Prinzip, wie im GoF-Buch beschrieben, bedeutet. In Wirklichkeit gilt es nur für Fälle, in denen Sie zwei separate Objekttypen benötigen oder bereits haben, einen für die Abstraktion (Schnittstelle) und einen anderen für eine Implementierung dieser Abstraktion. –

+0

Ich denke, Sie werden wahrscheinlich feststellen, dass die Klassen, die in einer gemeinsamen Spring-Anwendung in einander injiziert werden müssen, ** Service ** -Klassen sind, wie 'Dao's usw. Ich habe festgestellt, dass eine große Anzahl von diesen könnte möglicherweise alternative Implementierungen –

+1

Ja, wenn Sie mehrere Implementierungen haben, gilt das "Code für die Schnittstelle, nicht die Implementierung" -Prinzip. Aber Dinge wie "Wenn Sie an Schnittstellen codieren ..." ohne einen klaren Kontext zu sagen, ist irreführend und kann leicht von weniger erfahrenen Entwicklern falsch interpretiert werden.Die übermäßige Verwendung separater Schnittstellen verursacht großen Schaden, IMO. –

15

Ich stimme Ihrem Punkt zu - deshalb bevorzuge ich Konstruktor Injektion.

+2

+1 auf Konstruktor Injektion. Drückt Abhängigkeiten viel stärker aus und macht "witzige" Setter überflüssig – flq

+0

Konstruktorinjektion ++: Sobald Sie ein Objekt erstellt haben, muss es einsatzbereit und in einem konsistenten Zustand sein. – Kalecser

+2

Für den korrekten Betrieb der Klasse sind möglicherweise nicht alle Eigenschaften erforderlich. In diesem Fall injiziere ich sie immer durch Setter –

5

Sie (können) müssen einen Setter machen, die die Außenseite von einigen Ihrer internen Details informieren, aber es gibt keine Notwendigkeit, einen Getter zu machen. So enthüllen Sie einige Informationen, aber nicht wirklich zu viel; es ist nicht wirklich nützlich für etwas anderes als den beabsichtigten Zweck.

Zusätzlich würde ich empfehlen, nur Annotationen und @Autowired verwenden, in dem Fall, dass Sie keine öffentliches Setter machen müssen.

+0

+1 - befürworten Annotationen, wo immer es möglich ist, ist eine gute Sache. Ich versuche jetzt, den Sprung selbst zu machen, aber es ist schwer, diese XML-Gewohnheit zu brechen. – duffymo

3

Wenn Sie Feder Anmerkungen (@Autowired) können Sie DI private Mitglieder.

Wenn Sie lose Kopplung und (Einheit) Testbarkeit meiner Ansicht nach Quellen gehen bricht DI Informationen, die nicht ausgeblendet werden sollen.

0

Ich nehme an, es ist ein Kompromiss. Sie reduzieren festverdrahtete Abhängigkeiten, aber Sie können möglicherweise den Kern Ihrer Implementierung aufdecken. Mit den richtigen Abstraktionen können Sie dies ebenfalls reduzieren, aber dann erhöhen Sie die Komplexität der Codebasis (beispielsweise mit einer generischen "Verbindung", die eine LDAP-Verbindung oder eine SQL-Verbindung sein könnte).

Ich persönlich glaube nicht, Injektion mit Konstruktor es hilft, entweder, weil es konzeptionell ist.

Ich werde @Autowire überprüfen, tho‘.

tj

1

hatte ich hier die gleiche Frage im Grunde:

Encapsulation in the age of frameworks

ich die Antwort denken Konstruktor Injektion sein könnte. Wenn Sie Ihre Eigenschaften mit Settors versehen, ist es wirklich schwierig, alles zu verkapseln und einen guten Objektstatus beizubehalten.

1

verwendet Nie @Autowired, neige ich dazu, mit Hilfe von Parametern mögen in den Konstruktoren, aber manchmal ist es schwer zu verstehen, was die Parameter bedeuten, speziell wenn Sie viele Parameter haben - in diesem Fall bevorzuge ich den "Builder" -Ansatz, der in Effektivem Java beschrieben wird. Der Konstruktor empfängt das Erstellungsobjekt (das über Setter verfügt) und konstruiert sich damit. Die injizierten Attribute der Klasse sind endgültig (Unveränderlichkeit), die "Builder" -Klasse enthält Setter, aber keine Getter (dies muss nicht geschehen, da wir sie als innere Klasse der Klasse deklarieren, die konstruiert wird) und keine Setter benötigen die gerade für Frühling werden:

<bean id="runnable" class="MyClass"> 
    <constructor-arg> 
    <bean class="MyClass$Builder"> 
     <property name="p1" value="p1Value"/> 
     <property name="p2" value="p2Value"/> 
     <property name="p3" value="p3Value"/> 
     <property name="p4" value="p4Value"/> 
    </bean> 
    </constructor-arg> 
</bean> 

Class Code:

public class MyClass { 
    private final String p1; 
    private final String p2; 
    private final String p3; 
    private final String p4; 
    public MyClass(Builder builder) { 
     this.p1 = builder.p1; 
     this.p2 = builder.p2; 
     this.p3 = builder.p3; 
     this.p4 = builder.p4; 
    } 

    ... 

    public static class Builder { 
     private String p1; 
     private String p2; 
     private String p3; 
     private String p4; 
     public void setP1(String p1) { 
     this.p1 = p1; 
     } 
     ... and so on 
    } 
} 
0

nicht mit dem Punkt einig, dass der Frühling bricht Kapselung. Selbst wenn Sie Pojo haben, wo Sie in der Klasse ausgesetzt und gesetzt haben und dritte Partei Ihr Glas verbraucht, immer noch Chancen, dass Verbraucher von jar das Gleiche tun, was mit der Spring-Bean-Konfiguration möglich ist. (gilt für jede andere OOPs-Sprache)

Spring stellt nur eine Möglichkeit zur Verfügung, die über den Code ausgeführt werden kann und die Steuerung aus dem Code (IOC) herausbewegt hat.

Consumer (betrachten andere Programmierer verwendet Ihre Bibliothek), erstellt Bean durch die Feder-Konfiguration, immer noch Ihren Code haben Kontrolle. Kein Körper hält Sie daran, Eingaben zu validieren, die vom Benutzer gegeben wurden (das Spring-IOC-Framework durchläuft auch den gleichen Code, der von einer anderen Klasse verwendet wird, die Ihren Setter aufruft).

public void setAge(int age) { 
if (age < 0) { 
    throw new AppException("invalid age!"); 
} 
this.age=age; 
} 
0

Und das ist ein weiterer Grund, warum ich Guice bevorzugen;) Beide Guice und Spring JSR 330 DI-Spezifikation implementieren, aber mit Guice kann ich in meine private Instanz Felder spritzen ohne Setter ein Ich mag nicht Konstruktor Injektion wirklich, wie es schien, hat schwieriger zu refaktorieren. Es ist auch viel mehr tippen für nicht viel Wert in meiner bescheidenen Meinung.

später Dean

Verwandte Themen