@Resource vs @Autowired

2019-01-01 14:01发布

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?

11条回答
柔情千种
2楼-- · 2019-01-01 14:28

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楼-- · 2019-01-01 14:28

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

查看更多
情到深处是孤独
4楼-- · 2019-01-01 14:32

@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 :)

查看更多
何处买醉
5楼-- · 2019-01-01 14:35

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.
查看更多
人气声优
6楼-- · 2019-01-01 14:38

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

查看更多
梦寄多情
7楼-- · 2019-01-01 14:40

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.

查看更多
登录 后发表回答