@Resource vs @Autowired
Solution 1
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.
Solution 2
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.
So, basically 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, IMHO it causes a lot of confusion, because people are unaware of the conceptual difference and tend to use @Resource
for type-based autowiring.
Solution 3
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.
Solution 4
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
- Matches by Type
- Restricts by Qualifiers
- Matches by Name
@Resource
- Matches by Name
- Matches by Type
- Restricts by Qualifiers (ignored if match is found by name)
Which annotations (or combination of) should I use for injecting my beans?
-
Explicitly name your component [@Component("beanName")]
-
Use
@Resource
with thename
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
Solution 5
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.
mlo55
Updated on July 08, 2022Comments
-
mlo55 almost 2 years
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? -
Snekse over 12 yearsThis 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 inSomeBean
with aFoo
param? -
Snekse over 12 years@Snekse - Got my answer: stackoverflow.com/questions/3536674/…
-
Bozho over 12 yearsnope. You don't need any of that. Just the field. (Spring populates it via reflection)
-
Boris Treukhov over 11 yearsYes, 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 throworg.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. -
Boris Treukhov over 11 years@Bozho 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. -
Bozho over 11 yearsyes. 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 completeness
-
Stefan Haberl over 10 years+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
) -
Anver Sadhat over 10 yearsYou can refer the other post that tells the difference between this two when you try to use a simple MAP. stackoverflow.com/questions/13913752/…
-
Jules about 10 yearsNote that to use @Inject you need an additional dependency. Maven artifact and/or jar file download can be found here: search.maven.org/…
-
Jules about 10 years+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/…
-
Stephan almost 10 yearsFor the reader, please find a summary of the article pointed by @Jules here: stackoverflow.com/a/23887596/363573
-
Ricardo van den Broek almost 9 yearsOne 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. -
Daniel Alexiuc over 8 yearsNever gonna happen. And even if it did - doing a find/replace on annotation names is going to be the least of your problems.
-
jayendra bhatt about 7 years@autowire will be by type if it is written over a setter method , if its on the reference then it will be by name.
-
Ilya Serbis over 5 yearsFor the current version see docs.spring.io/spring/docs/current/spring-framework-reference/… (the tip was updated)
-
john16384 over 3 yearsSince 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 aname
, 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.