Understanding @Autowired vs @Resource: Core Injection Rules and Key Differences

The article explains how Spring's @Autowired and Java's @Resource annotations differ in their injection strategies, origins, matching priorities, and typical pitfalls, using a payment‑service example to illustrate each rule and provide practical guidance for avoiding common errors.

CTO Full-Stack Academy
CTO Full-Stack Academy
CTO Full-Stack Academy
Understanding @Autowired vs @Resource: Core Injection Rules and Key Differences

Spring's IoC container can be likened to a company's talent pool, where each bean is an employee identified by a role (the class or interface type) and a nickname (the bean name, defaulting to the class name with a lowercase first letter). Dependency injection means asking the container to assign the appropriate employee instead of creating one manually.

@Autowired is a Spring‑native annotation introduced in Spring 2.5. Its matching rule is by type first, then by name as a fallback . The process is:

Declare @Autowired private PaymentService paymentService; Spring searches the container for beans of type PaymentService.

Three possible outcomes:

✅ Exactly one bean found – it is injected.

⚠️ Multiple beans found – Spring falls back to the variable name (e.g., paymentService) and injects the bean whose name matches.

❌ No bean found – startup fails with a NoSuchBeanDefinitionException.

Advanced usage includes @Autowired(required = false) to suppress errors and return null, and combining with @Qualifier("beanName") to explicitly select a bean when multiple candidates exist.

@Resource follows the JSR‑250 standard, making it a framework‑agnostic injection rule. Its matching rule is by name first, then by type . Two cases exist:

When name is specified (e.g., @Resource(name="alipayPayment")), Spring strictly matches the bean name; if not found, an error is thrown without type fallback.

When no name is given, the variable name is used as the bean name. If that fails, Spring falls back to type matching; if multiple beans of that type exist, an error is raised.

Both annotations can also be combined with a type attribute for exact name‑and‑type matching.

Comparison summary (core dimensions):

Origin – @Autowired is Spring‑specific; @Resource is a Java standard (JSR‑250).

Matching priority – @Autowired: type → name; @Resource: name → type.

Multiple implementations – @Autowired resolves via variable name or @Qualifier; @Resource fails if name lookup yields multiple candidates.

Specification – @Autowired works with @Qualifier; @Resource works with name and optional type attributes.

Portability – @Autowired works only in Spring; @Resource is portable across containers that support JSR‑250.

Typical case study: multiple implementations of a payment service

public interface PaymentService {
    String pay(String orderId);
}

Two implementations:

@Service
public class AlipayPayment implements PaymentService {
    @Override
    public String pay(String orderId) {
        return "Alipay payment, order: " + orderId;
    }
}

@Service
public class WechatPayment implements PaymentService {
    @Override
    public String pay(String orderId) {
        return "Wechat payment, order: " + orderId;
    }
}

In OrderController different injection annotations are tested.

Scenario 1 – @Autowired with generic variable name

@Autowired
private PaymentService paymentService;

Result: Spring finds two beans of type PaymentService, then looks for a bean named paymentService, finds none, and throws NoUniqueBeanDefinitionException.

Scenario 2 – @Autowired with variable name matching a bean name

@Autowired
private PaymentService alipayPayment;

Result: Type match yields two beans; the variable name alipayPayment matches the default bean name of AlipayPayment, so that bean is injected.

Scenario 3 – @Autowired with @Qualifier

@Autowired
@Qualifier("wechatPayment")
private PaymentService paymentService;

Result: The qualifier directly selects the bean named wechatPayment, injection succeeds.

Scenario 4 – @Resource with matching variable name

@Resource
private PaymentService alipayPayment;

Result: Variable name is used as bean name, a matching bean is found, and injection succeeds.

Scenario 5 – @Resource with generic variable name

@Resource
private PaymentService paymentService;

Result: No bean named paymentService exists; Spring falls back to type matching, finds two beans, and throws an exception.

Scenario 6 – @Resource with explicit name

@Resource(name = "wechatPayment")
private PaymentService paymentService;

Result: Spring strictly looks for a bean named wechatPayment, finds it, verifies the type, and injects it.

Final conclusions :

If an interface has a single implementation, both annotations behave identically.

When multiple implementations exist, their differing matching logic becomes the primary source of bugs. @Autowired is suited for "type‑first" injection; @Resource excels at "name‑first" precise injection.

Common pitfalls and remedies :

Multiple implementations with @Autowired cause NoUniqueBeanDefinitionException. Fix by renaming the variable to match a bean name, adding @Qualifier, or switching to @Resource with an explicit name.

Incorrect bean name case (e.g., weChatPayment vs wechatPayment) leads to lookup failures. Ensure the variable name matches the default bean naming convention or specify the name explicitly.

Assuming the two annotations are interchangeable leads to sudden startup failures when a new implementation is added.

Using @Autowired(required = false) hides injection problems; a null reference will cause NPEs at runtime. Reserve this for truly optional dependencies and add null checks.

Production recommendations :

Single‑implementation projects can choose either annotation but keep usage consistent.

For multiple implementations, prefer @Resource(name="beanName") for clear intent and readability.

Pure Spring projects may stay with @Autowired to leverage Spring‑specific features like @Primary and @Qualifier.

When aiming for framework‑agnostic code, use @Resource to avoid Spring lock‑in.

Combine @Primary with @Autowired to designate a default bean and reduce the need for qualifiers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaspringdependency-injectionautowiredresourcebeanjsr-250
CTO Full-Stack Academy
Written by

CTO Full-Stack Academy

15 years of IT industry experience, sharing practical insights on pre-sales, product design, architecture, technology development, software testing, project management, IT consulting, and operations management.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.