What is the difference in default injection semantics between @Resource and @Autowired?
answer
- @Autowired = by type first
- @Resource = by name first
- name = field/property name default
- @Resource falls back to type
- @Resource: no constructor injection
basics
~10 s@Autowired matches a bean by its type first. @Resource (from jakarta.annotation) matches by name first, defaulting to the field or setter property name.
solid answer
~40 s@Autowired (Spring) resolves dependencies by type: it finds the bean whose class matches the injection point. If several match it narrows by @Qualifier or the field name. @Resource (jakarta.annotation.Resource, a Jakarta/JSR-250 annotation Spring supports) resolves by name: it looks up a bean whose id equals the 'name' attribute, or if that is omitted, the field/property name; only if no name match is found does it fall back to type. So the mental model is: @Autowired = by-type-primarily, @Resource = by-name-primarily. This matters when you have multiple beans of the same type: @Resource(name="...") or a matching field name selects one cleanly, whereas @Autowired needs @Qualifier to disambiguate.
code
java · 23 lines@Configuration
class DataSourceConfig {
@Bean DataSource primaryDataSource() { /* ... */ }
@Bean DataSource auditDataSource() { /* ... */ }
}
@Service
class ReportService {
// FAILS: NoUniqueBeanDefinitionException (two DataSource beans, by-type)
// @Autowired DataSource dataSource;
// WORKS: @Autowired needs an explicit qualifier
@Autowired @Qualifier("auditDataSource")
DataSource auditByAutowired;
// WORKS: @Resource matches the field name 'auditDataSource' by name
@Resource
DataSource auditDataSource;
// WORKS: explicit name attribute
@Resource(name = "primaryDataSource")
DataSource primary;
}go deeper
Must state the core contrast: @Autowired by type, @Resource by name.
Should mention the name defaults to the field/property name and the type fallback.
Should note constructor-injection limitation of @Resource and how @Autowired disambiguates via @Qualifier/@Primary/name fallback.
Frames it as resolution-order design and picks constructor+@Autowired as the default, reserving @Resource for deliberate by-name cases.
### The two annotations **@Autowired** is Spring's own annotation (`org.springframework.beans.factory.annotation.Autowired`). Its default resolution strategy is **by type**: Spring inspects the declared type of the field, constructor parameter, or setter argument, and finds the single bean in the ApplicationContext assignable to that type. **@Resource** is a Jakarta annotation (`jakarta.annotation.Resource`, formerly `javax.annotation.Resource`), part of the JSR-250 'Common Annotations' set. Spring's `CommonAnnotationBeanPostProcessor` processes it. Its default resolution strategy is **by name**. ### @Resource name resolution — the exact algorithm 1. If `@Resource(name="fooBar")` is given, Spring looks up a bean **named** `fooBar`. 2. If `name` is omitted, Spring **derives the name** from the injection point: the field name, or the JavaBean property name of the setter. 3. Spring looks up a bean with that derived name. If **exactly one** bean has that name, it is injected. 4. **Fallback:** if no bean matches by name, `@Resource` falls back to a **by-type** match (like @Autowired would). If that type match is ambiguous, it fails. So `@Resource` is *primarily by-name, secondarily by-type*. ### @Autowired resolution — the exact algorithm 1. Find all beans assignable to the injection point's type. 2. If exactly one → inject it. 3. If several → try to narrow: a `@Qualifier("...")` if present, then `@Primary`, then finally the **field/parameter name** used as a fallback qualifier (matching a bean id). 4. If still ambiguous or none → `NoUniqueBeanDefinitionException` / `NoSuchBeanDefinitionException` (unless `required=false`). So `@Autowired` is *primarily by-type, secondarily by-name (via qualifier fallback)*. ### Why the distinction matters — multiple beans of one type Suppose two `DataSource` beans, `primaryDataSource` and `auditDataSource`. - `@Autowired DataSource ds;` → **ambiguous**, throws `NoUniqueBeanDefinitionException`. You must add `@Qualifier("auditDataSource")` or name the field to match. - `@Resource DataSource auditDataSource;` → resolves cleanly, because the **field name** becomes the bean name to look up. No @Qualifier needed. ### Placement and constructor injection - `@Autowired` works on constructors, fields, and setters. Constructor injection is the Spring-recommended style. - `@Resource` works on **fields and setters/methods only** — it does **not** support constructor injection. This is a real limitation. ### Required vs optional - `@Autowired(required=false)` makes the dependency optional (null if absent). - `@Resource` has no `required` attribute; a missing dependency fails. (You'd use `@Autowired` or `Optional`/`ObjectProvider` for optionality.) ### When to use which - Prefer **constructor injection with @Autowired** (or no annotation on a single constructor) for mandatory collaborators — it enables immutability and easy testing. - `@Resource` is handy when you specifically want **by-name** selection among same-typed beans and dislike adding @Qualifier, or in codebases standardizing on Jakarta annotations. But it can't do constructor injection, so its use is narrower in modern Spring.
- If @Resource can't find a bean by name, what happens?It falls back to a by-type match. If exactly one bean of that type exists it is injected; if several exist it throws because the type match is now ambiguous.
- Can you use @Resource on a constructor parameter?No. @Resource only supports field and setter/method injection, not constructor injection. For constructor injection use @Autowired (or a single constructor with no annotation).