2015-11-06 12 views
18

Was ist der Unterschied zwischen anotate @Autowired zu einer Eigenschaft oder tun es im Setter?Feder @Autowire Eigenschaft vs Setter

Soweit ich weiß, haben beide das gleiche Ergebnis, aber gibt es einen Grund, einen über den anderen zu verwenden? zwischen diesem

package com.tutorialspoint; 

import org.springframework.beans.factory.annotation.Autowired; 

public class TextEditor { 
    private SpellChecker spellChecker; 

    @Autowired 
    public void setSpellChecker(SpellChecker spellChecker){ 
     this.spellChecker = spellChecker; 
    } 

    public void spellCheck() { 
     spellChecker.checkSpelling(); 
    } 
} 

und dieses

package com.tutorialspoint; 

import org.springframework.beans.factory.annotation.Autowired; 

public class TextEditor { 
    @Autowired 
    private SpellChecker spellChecker; 

    public TextEditor() { 
     System.out.println("Inside TextEditor constructor."); 
    } 

    public void spellCheck(){ 
     spellChecker.checkSpelling(); 
    } 
} 
+0

Ich weiß nicht, warum Antworten auf diese Frage würde rechthaberisch sein. Ich möchte wissen, ob es einen praktischen Unterschied zwischen der Verwendung von @Autowired in einem Setter oder direkt in der Eigenschaft gibt. Nicht fragen, welches ist besser, nur wenn es einen Unterschied gibt – luso

Antwort

14

Mit @Autowired Anmerkung

UPDATE ein Unterschied

Is (prägnanter zu sein), brauchen Sie nicht einen Setter Methode. Sobald der Bean-Konstruktor mit dem Zuordnen/Erstellen des Objekts fertig ist, sucht Spring nach dieser Annotation und fügt die von Ihnen kommentierten Objektinstanzen ein.

Wenn Sie Setter haben und wenn Sie immer noch XML Config verwenden, würden Sie explizit Eigenschaften festlegen.

Nachdem Sie das gesagt haben, könnten Sie Ihre Konstruktor und Setter-Methode mit AutoWire Annotation kommentieren, die ich bevorzugen würde, da dies mir später Flexibilität geben würde, um von Spring wegzukommen (obwohl ich es nicht mache).

+0

Wie in den Spring-Beispielen habe ich den Beitrag aktualisiert, gibt es einen Unterschied in DI-Begriffe? – luso

+0

Kein Unterschied, Sie injizieren immer noch die Abhängigkeit. Es ist nur Ihre Wahl durch Konstrukteur oder Setter für z.B. – SMA

0

Das automatische Abfahren funktioniert am besten, wenn es in einem Projekt konsistent verwendet wird. Wenn Autowiring im Allgemeinen nicht verwendet wird, kann es für Entwickler verwirrend sein, es zu verwenden, um nur eine oder zwei Bean-Definitionen zu verkabeln. Mit @Autowired auf einem Feld brauchst du keine Setter-Methode, die einerseits die Klasse kleiner und lesbarer macht, andererseits aber die Klasse etwas hässlicher macht.

Explizite Abhängigkeiten in Eigenschaften- und Konstruktor-Arg-Einstellungen überschreiben immer Autowiring. Sie können so genannte einfache Eigenschaften wie Primitive, Strings und Klassen (und Arrays solcher einfacher Eigenschaften) nicht automatisch ansteuern. Diese Einschränkung ist ein Design.

Autoschweißen ist weniger genau als explizite Verdrahtung. Spring ist vorsichtig, um zu vermeiden, dass im Fall von Mehrdeutigkeiten, die unerwartete Ergebnisse haben könnten, die Beziehungen zwischen Ihren von Spring verwalteten Objekten nicht explizit dokumentiert werden.

Verdrahtungsinformationen sind möglicherweise nicht für Tools verfügbar, die Dokumentation aus einem Spring-Container generieren können.

Mehrere Bean-Definitionen innerhalb des Containers können mit dem Typ übereinstimmen, der von der Setter-Methode oder dem Konstruktorargument angegeben wurde, das autowired werden soll. Für Arrays, Sammlungen oder Maps ist dies nicht unbedingt ein Problem. Bei Abhängigkeiten, die einen einzelnen Wert erwarten, wird diese Mehrdeutigkeit jedoch nicht willkürlich aufgelöst. Wenn keine eindeutige Bean-Definition verfügbar ist, wird eine Ausnahme ausgelöst.

1

Wenn Sie können, sollten Sie den Setter vermeiden. Wenn Sie es nicht brauchen, ist es besser, wenn es nicht existiert, oder?

Ich persönlich bevor Guice mir erlaubt

public class TextEditor { 
    private final SpellChecker spellChecker; 

    @Inject public TextEditor(SpellChecker spellChecker) { 
     this.spellChecker = spellChecker; 
    } 

    public void spellCheck(){ 
     spellChecker.checkSpelling(); 
    } 
} 

Das geht einen Schritt weiter zu schreiben: Mit einem final Feld, ich weiß, es wird nicht immer ändern und ich erhalte die multithreading visibility guarantee.

6

Manchmal benötigen Sie eine Instanz der Klasse A, aber Sie speichern A nicht im Feld der Klasse. Sie benötigen nur A, um eine einmalige Operation auszuführen.Oder Sie verwenden A, um eine Instanz von B zu erhalten, und Sie speichern B in dem Feld.

In diesen Fällen wird ein Setter (oder Konstruktor) Autowire Ihnen besser passen. Sie haben keine ungenutzten Felder auf Klassenebene.

Konkretes Beispiel: Sie benötigen RabbitTemplate zu konstruieren (ein Objekt, das Nachrichten an RabbitMQ sendet) es zu konstruieren, müssen Sie ConnectionFactory- http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-

Sie brauchen nicht, dass ConnectionFactory- zu speichern. In diesem Fall Code, der wie folgt aussieht:

Class MyClass { 
private RabbitTemplate template; 

@Autowired 
void setConnectionFactory(ConnectionFactory c) { 
    template=new RabbitTemplate(c); 
} 
} 

... servieren Sie besser als direkt autowiring das ConnectionFactory- Feld.

In diesem Beispiel wäre die automatische Erstellung auf Konstruktorebene noch besser, weil Ihr Objekt immer vollständig aufgebaut ist. Es wird klar sein, dass ConnectionFactory eine obligatorische Abhängigkeit ist, nicht eine optionale.

0

Wenn Sie @Autowired Anmerkung verwenden auf einem Eigenschaft, Frühling wird die Eigenschaft mit spring.xml initiieren. Sie brauchen in diesem Fall keinen Setter.

Wenn Sie @Autowired Anmerkung auf einem Setter verwenden, geben Sie an, zu springen, dass es diese Eigenschaft initiieren sollte diese Set-Methode verwenden, wo Sie Ihren eigenen Code hinzufügen können, wie mit dieser Eigenschaft eine andere Eigenschaft zu initialisieren .

Usage Beispiel: Im Fall von DAO Operationen mit Verwendung JdbcTemplate, müssen Sie Datasource als Eingabe in JdbcTemplate, aber Datasource wird nicht als Eigenschaft an sich erforderlich. Sie können also DataSource Setter verwenden, um JdbcTempate durch automatisches Verketten von DataSource Setter zu initialisieren. Bitte den Code unten sehen:

class DaoDemo{ 
    //@Autowired 
    //private DataSource dataSource; 
    private JdbcTemplate jdbcTemplate; 

    @Autowired 
    public void setDataSource(DataSource dataSource){ 
    //this.dataSource = dataSource; 
    this.jdbcTemplate = new JdbcTemplate(dataSource); 
    } 

    public int getTableRowCount(){ 
     String sql = "SELECT COUNT(*) FROM DEMOTABLE"; 
     //jdbcTemplate.setDataSource(dataSource); //No need to do this as its done in DataSource Setter now. 
     return jdbcTemplate.queryForObject(sql,Integer.class); 

} 

In dem obigen Code, der einzige Einsatz von Datasource war in JdbcTemplate weitergegeben werden. Daher macht das Erstellen einer Eigenschaft von dataSource hier keinen Sinn. Verwenden Sie einfach die @Autowired-on-Setter-Methode der DataSource-Bean, um ihren Eintrag aus der Datei spring.xml abzurufen und sie zu diesem Zeitpunkt selbst zu verwenden.

0

Es gibt einen Fall, in dem die Verwendung von @Autowired für eine OPTIONAL-Eigenschaft nicht funktioniert.

Wenn Sie eine Initialisierung mit dieser Eigenschaft durchführen möchten, wird sie möglicherweise nicht vor dem Aufruf des Konstruktors festgelegt, und da sie optional ist, können Sie sie nicht als Konstruktor verwenden.

In diesem Fall ist es besser, eine @Autowired-Setter-Methode zu verwenden, so dass Sie die Initialisierung durchführen können, sobald die Eigenschaft autowired ist.

Verwandte Themen