@Resource vs @Autowired

381

¿Qué anotación, @Resource ( jsr250 ) o @Autowired (Spring-specific) debo usar en DI?

He usado con éxito tanto en el pasado @Resource(name="blah")como@Autowired @Qualifier("blah")

Mi instinto es seguir con la @Resourceetiqueta, ya que ha sido ratificada por la gente jsr.
¿Alguien tiene pensamientos fuertes sobre esto?

mlo55
fuente
FYI: eliminé la 'actualización', debería haberse hecho como una pregunta separada. Según este comentario rechazado, "Esta edición se desvía de la intención original de la publicación. Incluso las ediciones que deben realizar cambios drásticos deben esforzarse por preservar los objetivos del propietario de la publicación"
mlo55

Respuestas:

195

En primavera pre-3.0 no importa cuál.

En la primavera 3.0 hay soporte para la anotación estándar ( JSR-330 ): úsela @javax.inject.Injectcon una combinación de @Qualifier. Tenga en cuenta que spring ahora también admite la @javax.inject.Qualifiermetaanotación:

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

Para que puedas tener

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

o

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

Y entonces:

@Inject @YourQualifier private Foo foo;

Esto hace menos uso de los nombres de cadena, que pueden estar mal escritos y son más difíciles de mantener.


En cuanto a la pregunta original: ambos, sin especificar ningún atributo de la anotación, realizan la inyección por tipo. La diferencia es:

  • @Resource le permite especificar un nombre del frijol inyectado
  • @Autowired le permite marcarlo como no obligatorio.
Bozho
fuente
Esto puede parecer una pregunta tonta, pero cuando usa este estilo de inyección, ¿necesita un setter público fooo un constructor SomeBeancon un Fooparámetro?
Snekse
@Snekse - Tengo mi respuesta: stackoverflow.com/questions/3536674/…
Snekse
no No necesitas nada de eso. Solo el campo. (La primavera lo llena a través de la reflexión)
Bozho
@Bozho Esta respuesta en realidad no muestra la diferencia entre @Resourcey @Autowired, la respuesta real es la publicada por @Ichthyo, creo que esta debe actualizarse.
Boris Treukhov
1
si. De hecho, a veces respondo preguntas proporcionando una mejor alternativa al enfoque. Pero
incluí
509

Ambos @Autowired(o @Inject) y @Resourcefuncionan igual de bien. Pero hay una diferencia conceptual o una diferencia en el significado

  • @Resourcesignifica conseguirme un recurso conocido por nombre . El nombre se extrae del nombre del configurador o campo anotado, o se toma del parámetro Nombre.
  • @Injecto @Autowiredintente conectar un otro componente adecuado por tipo .

Entonces, básicamente estos son dos conceptos bastante distintos. Desafortunadamente, la implementación de Spring @Resourcetiene un respaldo integrado, que se activa cuando falla la resolución por nombre. En este caso, @Autowiredrecurre a la resolución de tipo por tipo. Si bien este retroceso es conveniente, en mi humilde opinión, causa mucha confusión, porque las personas desconocen la diferencia conceptual y tienden a usar @Resourcepara el cableado automático basado en tipos.

Ichthyo
fuente
81
Sí, esto es lo que debería ser una respuesta aceptada. Por ejemplo, si tiene un @Resourcecampo anotado y el nombre del campo coincide con la identificación de un bean en el contenedor, Spring arrojará org.springframework.beans.factory.BeanNotOfRequiredTypeExceptionsi sus tipos difieren; esto se debe a que los beans se emparejan primero por nombre en @Resourceanotación, no por tipo. Pero si el nombre de la propiedad no coincide con el nombre del bean, Spring los conectará por tipo.
Boris Treukhov
Puede consultar la otra publicación que dice la diferencia entre estos dos cuando intenta usar un MAP simple. stackoverflow.com/questions/13913752/…
Anver Sadhat el
44
+1 por responder realmente la pregunta en lugar de simplemente recomendar una "mejor práctica" completamente diferente como lo hace la respuesta aceptada. También encontré útil esta publicación de blog, que muestra resultados de varios escenarios comunes con los tres estilos de anotación, útiles: blogs.sourceallies.com/2011/08/…
Jules
1
Para el lector, encuentre un resumen del artículo señalado por @Jules aquí: stackoverflow.com/a/23887596/363573
Stephan
3
Una implicación de esto: cuando desea inyectar un bean Map / List, @Autowireno puede y no funcionará. Tendrás que usar @Resourceen ese caso.
Ricardo van den Broek
76

La principal diferencia es, @Autowiredes una anotación de primavera. Mientras que @Resourceel JSR-250 lo especifica, como usted mismo señaló. Entonces, el último es parte de Java, mientras que el primero es específico de Spring.

Por lo tanto, tiene razón al sugerir eso, en cierto sentido. He encontrado gente utiliza @Autowiredcon @Qualifierporque es más potente. Pasar de un marco a otro se considera muy poco probable, si no un mito, especialmente en el caso de Spring.

Adeel Ansari
fuente
77
+1, porque @Autowiredcon @Qualifierrealmente es más poderoso que la @Resourceanotación estándar JSR (piense en dependencias opcionales, por ejemplo, con @Autowired(required=false). No puede hacer eso con @Resource)
Stefan Haberl
70

Me gustaría enfatizar un comentario de @Jules sobre esta respuesta a esta pregunta. El comentario trae un enlace útil: Spring Injection con @Resource, @Autowired y @Inject . Te animo a que lo leas por completo, sin embargo, aquí hay un resumen rápido de su utilidad:

¿Cómo las anotaciones seleccionan la implementación correcta?

@Autowired y @Inject

  1. Partidos por tipo
  2. Restricciones por calificadores
  3. Partidos por nombre

@Resource

  1. Partidos por nombre
  2. Partidos por tipo
  3. Restricciones por calificadores (ignorado si la coincidencia se encuentra por nombre)

¿Qué anotaciones (o combinación de) debo usar para inyectar mis frijoles?

  1. Nombre explícitamente su componente [@Component ("beanName")]

  2. Usar @Resourcecon el nameatributo [@Resource (name = "beanName")]

¿Por qué no debo usar @Qualifier?

Evite las @Qualifieranotaciones a menos que desee crear una lista de beans similares. Por ejemplo, es posible que desee marcar un conjunto de reglas con una @Qualifieranotación específica . Este enfoque simplifica la inyección de un grupo de clases de reglas en una lista que se puede usar para procesar datos.

¿La inyección de frijoles ralentiza mi programa?

Escanee paquetes específicos para componentes [context:component-scan base-package="com.sourceallies.person"]. Si bien esto dará como resultado más component-scanconfiguraciones, reduce la posibilidad de que agregue componentes innecesarios a su contexto Spring.


Referencia: inyección de primavera con @Resource, @Autowired y @Inject

Stephan
fuente
39

Esto es lo que obtuve del Manual de referencia de Spring 3.0.x : -

Propina

Si tiene la intención de expresar la inyección impulsada por anotaciones por nombre, no use principalmente @Autowired, incluso si es técnicamente capaz de referirse a un nombre de bean a través de los valores de @Qualifier. En su lugar, use la anotación JSR-250 @Resource, que se define semánticamente para identificar un componente de destino específico por su nombre único, con el tipo declarado irrelevante para el proceso de coincidencia.

Como consecuencia específica de esta diferencia semántica, los beans que se definen a sí mismos como una colección o un tipo de mapa no se pueden inyectar a través de @Autowired, porque la coincidencia de tipos no se aplica adecuadamente a ellos. Use @Resource para tales beans, refiriéndose a la colección específica o al bean de mapa por nombre único.

@Autowired se aplica a campos, constructores y métodos de múltiples argumentos, lo que permite reducir las anotaciones de calificador a nivel de parámetro. Por el contrario, @Resource solo se admite para campos y métodos de establecimiento de propiedades de bean con un único argumento. Como consecuencia, quédese con los calificadores si su objetivo de inyección es un constructor o un método de múltiples argumentos.

Kartik
fuente
Para la versión actual, ver docs.spring.io/spring/docs/current/spring-framework-reference/… (el consejo se actualizó)
Lu55
28

@Autowired + @Qualifier funcionará solo con Spring DI, si desea utilizar alguna otra DI en el futuro @Resource es una buena opción.

Otra diferencia que encontré muy significativa es que @Qualifier no admite el cableado de bean dinámico, ya que @Qualifier no admite el marcador de posición, mientras que @Resource lo hace muy bien.

Por ejemplo: si tiene una interfaz con múltiples implementaciones como esta

interface parent {

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

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

}

con @Autowired y @Qualifier necesita establecer una implementación secundaria específica como

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

que no proporciona marcador de posición, mientras que con @Resource puede colocar marcador de posición y usar el archivo de propiedades para inyectar una implementación secundaria específica como

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

donde service.name se establece en el archivo de propiedades como

#service.name=actualService
 service.name=stubbedService

Espero que ayude a alguien :)

Ali
fuente
16

Ambos son igualmente buenos. La ventaja de usar Resource es en el futuro si desea otro marco de DI que no sea Spring, sus cambios de código serán mucho más simples. Usando Autowired su código está estrechamente acoplado con resortes DI.

Teja Kantamneni
fuente
17
Nunca va a pasar. E incluso si lo hiciera, hacer una búsqueda / reemplazo en los nombres de las anotaciones será el menor de sus problemas.
Daniel Alexiuc
13

Cuando analice críticamente desde las clases base de estas dos anotaciones, se dará cuenta de las siguientes diferencias.

@Autowiredutiliza AutowiredAnnotationBeanPostProcessor para inyectar dependencias.
@Resourceutiliza CommonAnnotationBeanPostProcessorpara inyectar dependencias.

Aunque utilizan diferentes clases de postprocesador, todos se comportan de manera casi idéntica. Las diferencias se encuentran críticamente en sus rutas de ejecución, que he destacado a continuación.

@Autowired / @Inject

1. Emparejamientos por tipo
2. Restricciones por calificadores
3. Emparejamientos por nombre

@Resource

1. coincidencias por nombre
2. coincidencias por tipo
3. Restricciones por calificadores (se ignora si la coincidencia se encuentra por nombre)

Amos Kosgei
fuente
6

Con @Resource usted puede realizar la autoinyección de bean, puede ser necesario para ejecutar toda la lógica adicional agregada por los postprocesadores de bean como cosas transaccionales o relacionadas con la seguridad.

Con Spring 4.3+ @Autowiredtambién es capaz de hacer esto.

Bohdan Levchenko
fuente
2

@ResourceA menudo es utilizado por objetos de alto nivel, definidos a través de JNDI. @Autowiredo @Injectserá utilizado por frijoles más comunes.

Que yo sepa, no es una especificación, ni siquiera una convención. Es más la forma lógica en que el código estándar usará estas anotaciones.

Nicolas Zozol
fuente
0

Como una nota aquí: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContexty SpringBeanAutowiringSupport.processInjectionBasedOnServletContext NO funciona con @Resource anotaciones. Entonces, hay diferencia.

msangel
fuente