Understanding Spring @Autowired and @Resource Bean Injection and How to Choose Between Multiple Implementations
This article explains why a Spring interface bean can be injected without an explicit bean definition, compares the injection mechanisms of @Autowired and @Resource, and shows how to select a specific implementation when multiple beans implement the same interface.
The article addresses a common interview question about how a Spring interface bean is injected when only the implementation class is annotated with @Service , explaining that the container actually registers the implementation bean and the interface serves merely as a reference.
Example interface and implementation:
public interface TestService {
public String test();
} @Service
public class TestServiceImpl implements TestService {
@Override
public String test() {
return "TestServiceImpl";
}
}Controller usage:
@RestController
public class TestCtl {
@Autowired
private TestService testService;
@RequestMapping("/test")
public String test() {
return testService.test();
}
}The result shows that Spring injects the TestServiceImpl bean into the controller field of type TestService . The interface itself is not a bean; it is just a type used for injection.
Injection principles: @Autowired performs injection by type first, falling back to by‑name if multiple candidates exist; @Resource (a JDK annotation) defaults to by‑name, using the field name unless a name attribute is specified, and only falls back to by‑type when no matching name is found.
When the controller requests an instance, Spring looks for a bean of type TestService . Because there is exactly one such bean ( TestServiceImpl ), it is injected automatically. If @Resource were used, Spring would first try to find a bean named testService ; not finding one, it would then locate the unique TestService bean and inject it.
Handling multiple implementations: When more than one class implements the same interface, you can specify which bean to inject in two main ways:
1. Specify the bean name
Using @Autowired together with @Qualifier :
@Autowired
@Qualifier("testServiceImpl")
private TestService testService;Or using @Resource with the name attribute:
@Resource(name = "testServiceImpl")
private TestService testService;If @Resource is used without an explicit name, the field name is taken as the bean name, e.g.:
@Resource
private TestService testServiceImpl;2. Mark a bean as primary
Annotate the preferred implementation with @Primary :
@Service
@Primary
public class TestServiceImpl2 implements TestService {
@Override
public String test() {
return "TestServiceImpl2";
}
}Now, if no qualifier is provided, Spring will inject TestServiceImpl2 by default.
Why use an interface? Using an interface decouples callers from concrete implementations, enables AOP, promotes loose coupling and layered architecture, and allows polymorphism—multiple implementations can be swapped without changing client code. Directly injecting the implementation is possible but loses these design benefits.
Source: cnblogs.com/aland-1415/p/11991170.html
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.