@Resource vs @Autowired
Asked Answered
T

11

443

Which annotation, @Resource (jsr250) or @Autowired (Spring-specific) should I use in DI?

I have successfully used both in the past, @Resource(name="blah") and @Autowired @Qualifier("blah")

My instinct is to stick with the @Resource tag since it's been ratified by the jsr people.
Anyone has strong thoughts on this?

Throwback answered 4/11, 2010 at 2:50 Comment(1)
FYI - I removed the 'update', it should have been asked as a separate question. As per this rejected comment, "This edit deviates from the original intent of the post. Even edits that must make drastic changes should strive to preserve the goals of the post's owner"Throwback
O
213

In spring pre-3.0 it doesn't matter which one.

In spring 3.0 there's support for the standard (JSR-330) annotation @javax.inject.Inject - use it, with a combination of @Qualifier. Note that spring now also supports the @javax.inject.Qualifier meta-annotation:

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

So you can have

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

or

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

And then:

@Inject @YourQualifier private Foo foo;

This makes less use of String-names, which can be misspelled and are harder to maintain.


As for the original question: both, without specifying any attributes of the annotation, perform injection by type. The difference is:

  • @Resource allows you to specify a name of the injected bean
  • @Autowired allows you to mark it as non-mandatory.
Osage answered 4/11, 2010 at 9:21 Comment(6)
This might see like a silly question, but when you use this style of injection, do you need a public setter for foo or a constructor in SomeBean with a Foo param?Skip
@Skip - Got my answer: #3537174Skip
nope. You don't need any of that. Just the field. (Spring populates it via reflection)Osage
@Osage This answer actually does not show the difference between @Resource and @Autowired, actual answer is the one posted by @Ichthyo, I think this one must be updated.Cassiterite
yes. In fact I sometimes answer questions by providing a better alternative to the approach. But I included the answer to the original question below, for completenessOsage
Note that to use @Inject you need an additional dependency. Maven artifact and/or jar file download can be found here: search.maven.org/…Bananas
P
585

Both @Autowired (or @Inject) and @Resource work equally well. But there is a conceptual difference or a difference in the meaning

  • @Resource means get me a known resource by name. The name is extracted from the name of the annotated setter or field, or it is taken from the name-Parameter.
  • @Inject or @Autowired try to wire in a suitable other component by type.

These are two quite distinct concepts. Unfortunately, the Spring-Implementation of @Resource has a built-in fallback, which kicks in when resolution-by-name fails. In this case, it falls back to the @Autowired-kind resolution-by-type. While this fallback is convenient, it causes a lot of confusion, because people are unaware of the conceptual difference and tend to use @Resource for type-based autowiring.

Provisory answered 6/6, 2012 at 14:54 Comment(6)
Yes, this is what should be an accepted answer. For example if you have a @Resource annotated field, and field name matches the id of a bean in container then Spring will throw org.springframework.beans.factory.BeanNotOfRequiredTypeException if their types differ - this is because beans are first matched by name in @Resource annotation, not by type. But if name of the property doesn't match the name of the bean, then Spring will wire them by type.Cassiterite
+1 for actually answering the question rather than simply recommending an entirely different "best practice" as the accepted answer does. I also found this blog post, which shows results of several common scenarios with all three annotation styles, helpful: blogs.sourceallies.com/2011/08/…Bananas
For the reader, please find a summary of the article pointed by @Bananas here: https://mcmap.net/q/76702/-resource-vs-autowiredKiker
One implication of this: When you want to inject a Map/List bean, @Autowire can't and won't work. You will have to use @Resource in that case.Arctic
@autowire will be by type if it is written over a setter method , if its on the reference then it will be by name.Havenot
Since this answer confused me ("... @Resource has a built-in fallback, which kicks in when resolution by-name fails"), I'd like to point out that when using @Resource with a name, it will never ignore the name and fallback to inject something that only matches by type (Spring 5). If you use @Resource without specifying a name, then it does indeed inject by type. I think using @Resource without the name parameter should probably be considered bad practice.Glooming
O
213

In spring pre-3.0 it doesn't matter which one.

In spring 3.0 there's support for the standard (JSR-330) annotation @javax.inject.Inject - use it, with a combination of @Qualifier. Note that spring now also supports the @javax.inject.Qualifier meta-annotation:

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

So you can have

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

or

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

And then:

@Inject @YourQualifier private Foo foo;

This makes less use of String-names, which can be misspelled and are harder to maintain.


As for the original question: both, without specifying any attributes of the annotation, perform injection by type. The difference is:

  • @Resource allows you to specify a name of the injected bean
  • @Autowired allows you to mark it as non-mandatory.
Osage answered 4/11, 2010 at 9:21 Comment(6)
This might see like a silly question, but when you use this style of injection, do you need a public setter for foo or a constructor in SomeBean with a Foo param?Skip
@Skip - Got my answer: #3537174Skip
nope. You don't need any of that. Just the field. (Spring populates it via reflection)Osage
@Osage This answer actually does not show the difference between @Resource and @Autowired, actual answer is the one posted by @Ichthyo, I think this one must be updated.Cassiterite
yes. In fact I sometimes answer questions by providing a better alternative to the approach. But I included the answer to the original question below, for completenessOsage
Note that to use @Inject you need an additional dependency. Maven artifact and/or jar file download can be found here: search.maven.org/…Bananas
P
87

The primary difference is, @Autowired is a spring annotation. Whereas @Resource is specified by the JSR-250, as you pointed out yourself. So the latter is part of Java whereas the former is Spring specific.

Hence, you are right in suggesting that, in a sense. I found folks use @Autowired with @Qualifier because it is more powerful. Moving from some framework to some other is considered very unlikely, if not myth, especially in the case of Spring.

Phobos answered 4/11, 2010 at 3:39 Comment(1)
+1, because @Autowired with @Qualifier really is more powerful than the JSR standard @Resource annotation (think of optional dependencies for instance with @Autowired(required=false). You can't do that with @Resource)Interlineate
K
76

I would like to emphasize one comment from @Jules on this answer to this question. The comment brings a useful link: Spring Injection with @Resource, @Autowired and @Inject. I encourage you to read it entirely, however here is a quick summary of its usefulness:

How annotations select the right implementation?

@Autowired and @Inject

  1. Matches by Type
  2. Restricts by Qualifiers
  3. Matches by Name

@Resource

  1. Matches by Name
  2. Matches by Type
  3. Restricts by Qualifiers (ignored if match is found by name)

Which annotations (or combination of) should I use for injecting my beans?

  1. Explicitly name your component [@Component("beanName")]

  2. Use @Resource with the name attribute [@Resource(name="beanName")]

Why should I not use @Qualifier?

Avoid @Qualifier annotations unless you want to create a list of similar beans. For example you may want to mark a set of rules with a specific @Qualifier annotation. This approach makes it simple to inject a group of rule classes into a list that can be used for processing data.

Does bean injection slow my program?

Scan specific packages for components [context:component-scan base-package="com.sourceallies.person"]. While this will result in more component-scan configurations it reduces the chance that you’ll add unnecessary components to your Spring context.


Reference: Spring Injection with @Resource, @Autowired and @Inject

Kiker answered 27/5, 2014 at 10:56 Comment(0)
P
40

This is what I got from the Spring 3.0.x Reference Manual :-

Tip

If you intend to express annotation-driven injection by name, do not primarily use @Autowired, even if is technically capable of referring to a bean name through @Qualifier values. Instead, use the JSR-250 @Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.

As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot be injected through @Autowired, because type matching is not properly applicable to them. Use @Resource for such beans, referring to the specific collection or map bean by unique name.

@Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. By contrast, @Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, stick with qualifiers if your injection target is a constructor or a multi-argument method.

Pratique answered 24/9, 2013 at 9:26 Comment(1)
For the current version see docs.spring.io/spring/docs/current/spring-framework-reference/… (the tip was updated)Arthurarthurian
C
30

@Autowired + @Qualifier will work only with spring DI, if you want to use some other DI in future @Resource is good option.

other difference which I found very significant is @Qualifier does not support dynamic bean wiring, as @Qualifier does not support placeholder, while @Resource does it very well.

For example: if you have an interface with multiple implementations like this

interface parent {

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

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

}

with @Autowired & @Qualifier you need to set specific child implementation like

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

which does not provide placeholder while with @Resource you can put placeholder and use property file to inject specific child implementation like

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

where service.name is set in property file as

#service.name=actualService
 service.name=stubbedService

Hope that helps someone :)

Coraciiform answered 26/3, 2015 at 3:55 Comment(0)
M
19

Both of them are equally good. The advantage of using Resource is in future if you want to another DI framework other than spring, your code changes will be much simpler. Using Autowired your code is tightly coupled with springs DI.

Miracle answered 4/11, 2010 at 2:59 Comment(1)
Never gonna happen. And even if it did - doing a find/replace on annotation names is going to be the least of your problems.Duplicate
C
19

When you analyze critically from the base classes of these two annotations.You will realize the following differences.

@Autowired uses AutowiredAnnotationBeanPostProcessor to inject dependencies.
@Resource uses CommonAnnotationBeanPostProcessor to inject dependencies.

Even though they use different post processor classes they all behave nearly identically. The differences critically lie in their execution paths, which I have highlighted below.

@Autowired / @Inject

1.Matches by Type
2.Restricts by Qualifiers
3.Matches by Name

@Resource

1.Matches by Name
2.Matches by Type
3.Restricts by Qualifiers (ignored if match is found by name)

Caernarvonshire answered 5/10, 2018 at 11:23 Comment(0)
P
6

With @Resource you can do bean self-injection, it might be needed in order to run all extra logic added by bean post processors like transactional or security related stuff.

With Spring 4.3+ @Autowired is also capable of doing this.

Pennyworth answered 20/6, 2017 at 20:25 Comment(0)
D
2

@Resource is often used by high-level objects, defined via JNDI. @Autowired or @Inject will be used by more common beans.

As far as I know, it's not a specification, nor even a convention. It's more the logical way standard code will use these annotations.

Documentation answered 7/3, 2014 at 18:6 Comment(0)
G
0

As a note here: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext and SpringBeanAutowiringSupport.processInjectionBasedOnServletContext DOES NOT work with @Resource annotation. So, there are difference.

Grisons answered 17/6, 2013 at 17:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.