可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答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.
回答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.
回答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.
回答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 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
回答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.
回答6:
@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 :)
回答7:
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.
回答8:
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.
回答9:
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)
回答10:
@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.
回答11:
As a note here:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext
and SpringBeanAutowiringSupport.processInjectionBasedOnServletContext
DOES NOT work with @Resource
annotation. So, there are difference.