@Resource vs @Autowired


381

Quale annotazione, @Resource ( jsr250 ) o @Autowired (specifica per la primavera) dovrei usare in DI?

Ho usato con successo sia in passato, @Resource(name="blah")sia@Autowired @Qualifier("blah")

Il mio istinto è quello di @Resourceattenermi all'etichetta poiché è stata ratificata dal popolo jsr.
Qualcuno ha forti pensieri su questo?


Cordiali saluti - Ho rimosso l '"aggiornamento", avrebbe dovuto essere posto come una domanda separata. Come da questo commento respinto, "Questa modifica si discosta dall'intento originale del post. Anche le modifiche che devono apportare modifiche drastiche dovrebbero sforzarsi di preservare gli obiettivi del proprietario del post"
mlo55

Risposte:


195

In primavera pre-3.0 non importa quale.

Nella primavera 3.0 c'è il supporto per l' annotazione standard ( JSR-330 ) @javax.inject.Inject- usala , con una combinazione di @Qualifier. Nota che ora la primavera supporta anche la @javax.inject.Qualifiermeta-annotazione:

@Qualifier
@Retention(RUNTIME)
public @interface YourQualifier {}

Quindi puoi avere

<bean class="com.pkg.SomeBean">
   <qualifier type="YourQualifier"/>
</bean>

o

@YourQualifier
@Component
public class SomeBean implements Foo { .. }

E poi:

@Inject @YourQualifier private Foo foo;

Questo fa meno uso dei nomi di stringhe, che possono essere scritti in modo errato e sono più difficili da mantenere.


Per quanto riguarda la domanda originale: entrambi, senza specificare alcun attributo dell'annotazione, eseguono l'iniezione per tipo. La differenza è:

  • @Resource consente di specificare un nome del bean iniettato
  • @Autowired ti consente di contrassegnarlo come non obbligatorio.

Potrebbe sembrare una domanda sciocca, ma quando usi questo stile di iniezione, hai bisogno di un setter pubblico fooo di un costruttore SomeBeancon un Fooparametro?
Snekse,

@Snekse - Ha ottenuto la mia risposta: stackoverflow.com/questions/3536674/...
Snekse

no. Non ti serve nulla di tutto ciò. Proprio il campo. (La primavera lo popola attraverso la riflessione)
Bozho,

@Bozho Questa risposta in realtà non mostra la differenza tra @Resourcee @Autowired, la risposta effettiva è quella pubblicata da @Ichthyo, penso che questa debba essere aggiornata.
Boris Treukhov,

1
sì. Infatti a volte rispondo alle domande fornendo un'alternativa migliore all'approccio. Ma ho incluso la risposta alla domanda originale qui sotto, per completezza
Bozho,

509

Entrambi @Autowired(o @Inject) e @Resourcefunzionano ugualmente bene. Ma c'è una differenza concettuale o una differenza nel significato

  • @Resourcesignifica procurarmi una risorsa nota per nome . Il nome viene estratto dal nome del setter o campo annotato, oppure è preso dal nome-parametro.
  • @Injectoppure @Autowiredprova a collegare un altro componente adatto per tipo .

Quindi, sostanzialmente questi sono due concetti abbastanza distinti. Sfortunatamente la Spring-Implementation di @Resourceha un fallback integrato, che si avvia quando la risoluzione per nome fallisce. In questo caso, ritorna alla @Autowiredrisoluzione tipo per tipo. Mentre questo fallback è conveniente, IMHO provoca molta confusione, perché le persone non sono consapevoli della differenza concettuale e tendono ad usare @Resourceper l'autowiring basato sul tipo.


81
Sì, questa è quella che dovrebbe essere una risposta accettata. Ad esempio, se si dispone di un @Resourcecampo annotato e il nome del campo corrisponde all'ID di un bean nel contenitore, Spring lancerà org.springframework.beans.factory.BeanNotOfRequiredTypeExceptionse i loro tipi differiscono: questo perché i bean vengono prima abbinati per nome nell'annotazione @Resource, non per tipo. Ma se il nome della proprietà non corrisponde al nome del bean, Spring li collegherà per tipo.
Boris Treukhov,

È possibile fare riferimento all'altro post che indica la differenza tra questi due quando si tenta di utilizzare un semplice MAP. stackoverflow.com/questions/13913752/...
Anver Sadhat

4
+1 per aver effettivamente risposto alla domanda piuttosto che semplicemente raccomandare una "best practice" completamente diversa come fa la risposta accettata. Ho anche trovato utile questo post sul blog, che mostra i risultati di diversi scenari comuni con tutti e tre gli stili di annotazione: blogs.sourceallies.com/2011/08/…
Jules

1
Per il lettore, si prega di trovare una sintesi dell'articolo puntato da @Jules qui: stackoverflow.com/a/23887596/363573
Stephan

3
Una conseguenza di ciò: quando si desidera iniettare un bean Map / List, @Autowirenon può e non funziona. Dovrai usare @Resourcein quel caso.
Ricardo van den Broek,

76

La differenza principale è che @Autowiredè un'annotazione di primavera. Considerando che @Resourceè specificato dal JSR-250, come hai sottolineato te stesso. Quindi il secondo fa parte di Java, mentre il primo è specifico per Spring.

Quindi, hai ragione nel suggerirlo, in un certo senso. Ho trovato persone utilizzano @Autowiredcon @Qualifierperché è più potente. Passare da una struttura all'altra è considerato molto improbabile, se non addirittura mito, soprattutto nel caso della primavera.


7
+1, perché @Autowiredcon @Qualifierdavvero è più potente @Resourcedell'annotazione standard JSR (pensa alle dipendenze opzionali per esempio con @Autowired(required=false). Non puoi farlo con @Resource)
Stefan Haberl

70

Vorrei sottolineare un commento di @Jules su questa risposta a questa domanda. Il commento porta un link utile: Spring Injection con @Resource, @Autowired e @Inject . Ti incoraggio a leggerlo interamente, tuttavia ecco un breve riassunto della sua utilità:

In che modo le annotazioni selezionano la corretta implementazione?

@Autowired e @Inject

  1. Corrisponde per tipo
  2. Limitazioni per qualificatori
  3. Corrispondenze per nome

@Resource

  1. Corrispondenze per nome
  2. Corrisponde per tipo
  3. Limitazioni per qualificatori (ignorato se viene trovata la corrispondenza per nome)

Quali annotazioni (o combinazioni di) dovrei usare per iniettare i miei bean?

  1. Denominare esplicitamente il componente [@Component ("beanName")]

  2. Utilizzare @Resourcecon l' nameattributo [@Resource (name = "beanName")]

Perché non dovrei usare @Qualifier?

Evita le @Qualifierannotazioni a meno che non desideri creare un elenco di bean simili. Ad esempio, potresti voler contrassegnare un insieme di regole con @Qualifierun'annotazione specifica . Questo approccio semplifica l'iniezione di un gruppo di classi di regole in un elenco che può essere utilizzato per l'elaborazione dei dati.

L'iniezione di fagioli rallenta il mio programma?

Scansione di pacchetti specifici per componenti [context:component-scan base-package="com.sourceallies.person"]. Sebbene ciò comporti più component-scanconfigurazioni, riduce la possibilità di aggiungere componenti non necessari al contesto Spring.


Riferimento: Spring Injection con @Resource, @Autowired e @Inject


39

Questo è ciò che ho ottenuto dal Manuale di riferimento di Spring 3.0.x : -

Mancia

Se si intende esprimere l'iniezione guidata dall'annotazione in base al nome, non utilizzare principalmente @Autowired, anche se è tecnicamente in grado di fare riferimento al nome di un bean attraverso i valori di @Qualifier. Utilizzare invece l'annotazione JSR-250 @Resource, che è semanticamente definita per identificare uno specifico componente di destinazione con il suo nome univoco, con il tipo dichiarato non pertinente per il processo di abbinamento.

Come conseguenza specifica di questa differenza semantica, i bean che sono essi stessi definiti come un tipo di raccolta o di mappa non possono essere iniettati tramite @Autowired, poiché la corrispondenza dei tipi non è propriamente applicabile. Utilizzare @Resource per tali bean, facendo riferimento alla raccolta specifica o al bean di mappa con un nome univoco.

@Autowired si applica a campi, costruttori e metodi multi-argomento, consentendo di restringere le annotazioni del qualificatore a livello di parametro. Al contrario, @Resource è supportato solo per i campi e i metodi di impostazione delle proprietà del bean con un singolo argomento. Di conseguenza, attenersi ai qualificatori se il target di iniezione è un costruttore o un metodo multi-argomento.


Per la versione corrente consultare docs.spring.io/spring/docs/current/spring-framework-reference/… (il suggerimento è stato aggiornato)
Lu55

28

@Autowired + @Qualifier funzionerà solo con DI primavera, se si desidera utilizzare qualche altro DI in futuro, @Resource è una buona opzione.

altra differenza che ho trovato molto significativo è che @Qualifier non supporta il cablaggio del bean dinamico, poiché @Qualifier non supporta il segnaposto, mentre @Resource lo fa molto bene.

Ad esempio: se si dispone di un'interfaccia con più implementazioni come questa

interface parent {

}
@Service("actualService")
class ActualService implements parent{

}
@Service("stubbedService")
class SubbedService implements parent{

}

con @Autowired & @Qualifier è necessario impostare un'implementazione figlio specifica come

@Autowired
@Qualifier("actualService") or 
@Qualifier("stubbedService") 
Parent object;

che non fornisce segnaposto mentre con @Resource è possibile inserire segnaposto e utilizzare il file delle proprietà per iniettare un'implementazione figlio specifica come

@Resource(name="${service.name}")
Parent object;  

dove service.name è impostato nel file delle proprietà come

#service.name=actualService
 service.name=stubbedService

Spero che aiuti qualcuno :)


16

Entrambi sono ugualmente buoni. Il vantaggio dell'utilizzo di Resource è in futuro se si desidera un altro framework DI diverso da Spring, le modifiche al codice saranno molto più semplici. Usando Autowired il tuo codice è strettamente associato alle molle DI.


17
Non succederà mai. E anche se lo facesse - fare un trova / sostituisci sui nomi delle annotazioni sarà l'ultimo dei tuoi problemi.
Daniel Alexiuc,

13

Quando analizzi criticamente dalle classi di base di queste due annotazioni, realizzerai le seguenti differenze.

@Autowiredutilizza AutowiredAnnotationBeanPostProcessor per iniettare dipendenze.
@Resourceutilizza CommonAnnotationBeanPostProcessorper iniettare dipendenze.

Anche se usano classi di post-processore diverse, si comportano tutte in modo quasi identico. Le differenze risiedono in modo critico nei loro percorsi di esecuzione, che ho evidenziato di seguito.

@Autowired / @Inject

1. Corrispondenze per tipo
2. Limitazioni per qualificazioni
3. Corrispondenze per nome

@Resource

1. Corrispondenze per nome
2. Corrispondenze per tipo
3. Restrizione per qualificatori (ignorata se la corrispondenza viene rilevata per nome)


6

Con @Resourcete puoi fare l'autoiniezione di bean, potrebbe essere necessario per eseguire tutta la logica aggiuntiva aggiunta dai processori di post bean come roba transazionale o relativa alla sicurezza.

Con Spring 4.3+ @Autowiredè anche in grado di farlo.


2

@Resourceviene spesso utilizzato da oggetti di alto livello, definiti tramite JNDI. @Autowiredo @Injectsarà utilizzato da fagioli più comuni.

Per quanto ne so, non è una specifica, né una convenzione. È più logico il modo in cui il codice standard utilizzerà queste annotazioni.


0

Come nota qui: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContexte SpringBeanAutowiringSupport.processInjectionBasedOnServletContext NON funziona con le @Resource annotazioni. Quindi, ci sono differenze.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.