Differences Between @Autowired, @Resource, and @Inject and Why Field Injection Is Not Recommended in Spring
This article explains the distinctions among Spring's @Autowired, @Resource, and @Inject annotations, describes the IDE warning "Field injection is not recommended", compares field, setter, and constructor injection methods, and provides best‑practice recommendations with code examples.
Preface
This chapter investigates several key points of dependency injection in Spring development, focusing on the differences between @Autowired , @Resource , and @Inject , the IDEA warning "Field injection is not recommended", and the recommended injection approaches.
Differences Between @Autowired, @Resource, and @Inject
Spring supports three annotations for dependency injection:
@Autowired
@Resource
@Inject
Below are the details of each annotation.
@Autowired
@Autowired is provided by Spring and requires the import org.springframework.beans.factory.annotation.Autowired . The following example demonstrates its usage:
public interface Svc {
void sayHello();
}
@Service
public class SvcA implements Svc {
@Override
public void sayHello() {
System.out.println("hello, this is service A");
}
}
@Service
public class SvcB implements Svc {
@Override
public void sayHello() {
System.out.println("hello, this is service B");
}
}
@Service
public class SvcC implements Svc {
@Override
public void sayHello() {
System.out.println("hello, this is service C");
}
}Test class:
@SpringBootTest
public class SimpleTest {
@Autowired
// @Qualifier("svcA")
Svc svc;
@Test
void rc() {
Assertions.assertNotNull(svc);
svc.sayHello();
}
}Injection order for @Autowired :
Search by type in the application context.
If multiple beans match, match by name .
If a @Qualifier is present, match the specified name.
If no qualifier, match by variable name.
If no match is found, an error is thrown (unless @Autowired(required=false) is used).
@Inject
In a Spring environment, @Inject behaves the same as @Autowired because both are processed by AutowiredAnnotationBeanPostProcessor . @Inject is defined by JSR‑330, so it can also be used with Google Guice.
Key differences:
@Inject belongs to the Java EE package and must be added separately in a SE environment.
Unlike @Autowired , @Inject does not have the required attribute.
@Resource
@Resource is defined by JSR‑250 and is processed by Spring's CommonAnnotationBeanPostProcessor . It has two important attributes: name and type . The name attribute resolves to the bean name, while type resolves to the bean type.
Injection order for @Resource :
If both name and type are specified, Spring looks for a unique matching bean; otherwise an exception is thrown.
If only name is specified, Spring matches by bean name.
If only type is specified, Spring matches by type; multiple matches cause an exception.
If neither is specified, Spring first tries byName , then byType .
IDEA Warning: Field injection is not recommended
When using @Autowired on a field, IntelliJ IDEA shows the warning "Field injection is not recommended" with the inspection message: "Spring Team Recommends: Always use constructor‑based dependency injection in your beans. Always use assertions for mandatory dependencies."
Translation of the warning:
Do not use field‑based injection. The Spring development team recommends using constructor‑based injection for mandatory dependencies and asserting non‑null values.
Example of converting field injection to constructor injection (IDEA quick‑fix Alt+Enter):
@Service
public class HelpService {
private final Svc svc;
@Autowired
public HelpService(@Qualifier("svcB") Svc svc) {
// Assert.notNull(svc, "svc must not be null");
this.svc = svc;
}
public void sayHello() {
svc.sayHello();
}
}Three Injection Styles in Spring
Field injection (property injection)
Setter injection
Constructor injection
1. Field Injection
Directly annotates a field, e.g. @Autowired private Svc svc; . It is concise but has several drawbacks:
Can violate the Single Responsibility Principle by encouraging many dependencies.
Creates strong coupling with the container, making the class hard to instantiate outside the container.
Prevents creation of immutable objects (cannot use final fields).
2. Setter Injection
Uses a setter method annotated with @Autowired , e.g.: private Helper helper; @Autowired public void setHelper(Helper helper) { this.helper = helper; } Since Spring 4.3, the @Autowired on a single‑argument setter can be omitted. 3. Constructor Injection All mandatory dependencies are declared as constructor parameters, e.g.: private final Svc svc; @Autowired public HelpService(@Qualifier("svcB") Svc svc) { this.svc = svc; } Since Spring 4.3, if a class has only one constructor, the @Autowired annotation can be omitted. Spring Team Recommendations Use constructors for mandatory dependencies and setter or configuration methods for optional ones. Key points: Constructor injection enables immutable components and guarantees that required dependencies are not null. A large number of constructor arguments is a code smell indicating too many responsibilities. Setter injection should be limited to optional dependencies; otherwise, null checks become pervasive. Conclusion The article provides a comprehensive overview of Spring dependency injection, the differences among @Autowired , @Resource , and @Inject , the rationale behind avoiding field injection, and best‑practice guidelines for choosing the appropriate injection method.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.