2015-11-06 20 views
18

Qual è la differenza tra anotate @Autowired a una proprietà o nel setter?spring @Autowire property vs setter

Per quanto ne so entrambi hanno lo stesso risultato, ma c'è qualche ragione per usarne uno sull'altro?

UPDATE (per essere più conciso)

C'è una differenza tra questo

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(); 
    } 
} 

e questo

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

Non so perché le risposte a questa domanda sarebbero state giudicate. Voglio sapere se c'è una differenza pratica tra l'uso di @Autowired in un setter o direttamente nella proprietà. Non chiedere quale sia migliore, solo se c'è una differenza – luso

risposta

14

Con @Autowired annotazioni, non è necessario un setter metodo. Una volta che il costruttore del bean ha terminato l'allocazione/creazione dell'oggetto, Spring eseguirà la scansione di questa annotazione e inserirà le istanze dell'oggetto annotate.

Mentre se si dispone del setter e se si sta ancora utilizzando la configurazione xml, si impostano esplicitamente le proprietà.

Detto questo, è possibile annotare il metodo costruttore e setter con annotazione autowired che preferirei in quanto ciò mi darebbe flessibilità in seguito per passare da Spring (anche se non lo farò).

+0

Come negli esempi di primavera che ho usato per aggiornare il post, c'è qualche differenza nei termini di DI? – luso

+0

Nessuna differenza, stai ancora iniettando la dipendenza. È solo una tua scelta per costruttore o setter per es. – SMA

0

Autowiring funziona in modo ottimale quando viene utilizzato in modo coerente in un progetto. Se l'autowiring non viene utilizzato in generale, potrebbe essere fonte di confusione per gli sviluppatori utilizzarlo per collegare solo una o due definizioni di bean. Con @Autowired su un campo non hai bisogno di un metodo setter, che, da un lato, rende la classe più piccola e più facile da leggere, ma d'altra parte rende la classe un po 'più brutta.

Le dipendenze esplicite nelle impostazioni di proprietà e di costruttore annullano sempre l'autowiring. Non è possibile rendere autonome le cosiddette proprietà semplici come primitive, stringhe e classi (e le matrici di tali proprietà semplici). Questa limitazione è by-design.

L'autowiring è meno esatto del cablaggio esplicito. Spring fa attenzione a non indovinare in caso di ambiguità che potrebbe avere risultati imprevisti, le relazioni tra gli oggetti gestiti da Spring non sono più documentate esplicitamente.

Le informazioni sul cablaggio potrebbero non essere disponibili per gli strumenti che potrebbero generare documentazione da un contenitore Spring.

Le definizioni di più bean all'interno del contenitore possono corrispondere al tipo specificato dal metodo setter o dall'argomento costruttore da eseguire automaticamente. Per array, raccolte o mappe, questo non è necessariamente un problema. Tuttavia, per le dipendenze che prevedono un singolo valore, questa ambiguità non viene risolta arbitrariamente. Se non è disponibile alcuna definizione di bean univoca, viene generata un'eccezione.

1

Se è possibile, è necessario evitare il setter. Se non ne hai bisogno, è meglio quando non esiste, giusto?

Io personalmente preferisco Guice che mi permette di scrivere

public class TextEditor { 
    private final SpellChecker spellChecker; 

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

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

Questo va oltre un passo: Con un campo final, so che non cambierà mai e ottengo il multithreading visibility guarantee.

6

A volte è necessaria un'istanza di classe A, ma non si memorizza A nel campo della classe. Hai solo bisogno di A per eseguire un'operazione one-shot.Oppure, si utilizza A per ottenere un'istanza di B e si sta memorizzando B nel campo.

In questi casi, un setter (o costruttore) autowire farà al caso vostro. Non avrai campi inutilizzati a livello di classe.

Esempio concreto: è necessario costruire RabbitTemplate (un oggetto che invia messaggi a RabbitMQ) Per costruire, è necessario 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-

Non è necessario per memorizzare che ConnectionFactory. In questo caso, il codice che assomiglia a questo:

Class MyClass { 
private RabbitTemplate template; 

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

... vi servirà meglio di autowiring direttamente il campo ConnectionFactory.

In questo esempio, l'autowiring a livello di costruttore sarebbe ancora meglio, perché il tuo oggetto sarà sempre completamente costruito. Sarà chiaro che ConnectionFactory è una dipendenza obbligatoria, non opzionale.

0

Se si utilizza @Autowired annotazioni su un proprietà, primavera avvierà la struttura utilizzando spring.xml. In questo caso non hai bisogno di setter.

Se si utilizza @Autowired annotazioni su un setter, si specifica alla primavera che dovrebbe avviare questa proprietà usando questo metodo setter in cui è possibile aggiungere il codice personalizzato, come inizializzazione qualche altra proprietà con questa proprietà .

Usage con Esempio: Nel caso di utilizzo di operazioni DAO utilizzando JdbcTemplate, è necessario DataSource come input per JdbcTemplate, ma DataSource non è richiesto come struttura in sé. Pertanto, è possibile utilizzare DataSource Setter per inizializzare JdbcTempate tramite il cablaggio automatico DataSource Setter. Si prega di consultare il codice qui sotto:

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); 

} 

Nel codice precedente, il solo uso di dataSource è stato quello di avere superato in JdbcTemplate. Quindi, creare una proprietà di dataSource non ha senso qui. Quindi, basta usare il metodo @Autowired on setter del bean DataSource per ottenere la sua voce da spring.xml e utilizzarlo in quel particolare momento.

0

C'è un caso in cui l'utilizzo di @Autowired su una proprietà OPTIONAL non funzionava.

Se si desidera eseguire l'inizializzazione utilizzando tale proprietà, potrebbe non essere impostato prima che venga chiamato il costruttore, e poiché è facoltativo, non è possibile inserirlo come argomento nel costruttore.

In tal caso è preferibile utilizzare un metodo di settaggio @Autowired, in modo da poter eseguire l'inizializzazione una volta che la proprietà è stata autorizzata.

Problemi correlati