1. Introduction
The @Inject annotation is part of Java’s standard dependency injection specification, defined in JSR-330 (Java Specification Request). It allows you to inject dependencies into Spring-managed beans in a way that’s decoupled from the Spring framework itself.
2. What is @Inject?
@Inject is a standard annotation provided by Javax Dependency Injection API (javax.inject.Inject) for constructor, field, or setter-based dependency injection.
It was introduced to standardize dependency injection across Java frameworks like Spring, Google Guice, etc.
Package:
import javax.inject.Inject;
To use it, your project must include the JSR-330 dependency (Spring Boot includes this transitively through Spring Core).
3. Comparison: @Inject vs @Autowired
| Feature | @Inject | @Autowired |
| Origin | JSR-330 (javax.inject.Inject) | Spring-specific |
| Required Dependency | Always required (no required flag) | Has required flag (optional deps) |
| Default behavior | Inject by type | Inject by type |
| Support for Qualifiers | Yes, with @Named | Yes, with @Qualifier |
| Preferred in… | Framework-independent code | Spring-specific applications |
4. When to Use @Inject
Use @Inject when:
- You want to write framework-agnostic code
- You want to promote clean architecture (not tightly coupled with Spring)
- You’re building libraries or components that might be used with Guice, Spring, or other DI frameworks
5. How to Use @Inject in Spring Boot
Spring Boot supports @Inject just like @Autowired, thanks to Spring’s support for the JSR-330 standard.
A. Field Injection
@Component
public class NotificationService {
@Inject
private EmailService emailService;
public void send(String to, String message) {
emailService.sendEmail(to, message);
}
}
B. Constructor Injection (Recommended)
@Component
public class NotificationService {
private final EmailService emailService;
@Inject
public NotificationService(EmailService emailService) {
this.emailService = emailService;
}
public void send(String to, String message) {
emailService.sendEmail(to, message);
}
}
Constructor injection is preferred because:
- It makes dependencies explicit
- Enables better testability
- Ensures immutability of fields
C. Setter Injection
@Component
public class NotificationService {
private EmailService emailService;
@Inject
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
6. Using @Named with @Inject (Like @Qualifier)
If you have multiple beans of the same type, use @Named to specify which one to inject:
@Component
@Named("email")
public class EmailService implements MessageService {
public void sendMessage(String msg) {
System.out.println("Email: " + msg);
}
}
@Component
@Named("sms")
public class SMSService implements MessageService {
public void sendMessage(String msg) {
System.out.println("SMS: " + msg);
}
}
@Component
public class NotificationService {
@Inject
@Named("sms")
private MessageService messageService;
public void notify(String msg) {
messageService.sendMessage(msg);
}
}
7. Requirements for Using @Inject
Spring Boot includes support for @Inject out of the box.
If you’re using plain Spring (not Boot), you may need to add this dependency:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
In Spring Boot, this is already included via spring-boot-starter.
8. Best Practices
- Prefer constructor injection: Clearer and better for testing
- Use
@Injectfor portability: Especially in reusable libraries - Use
@Namedwith@Injectcarefully: It’s equivalent to@Qualifier, but less powerful - Avoid mixing
@Injectand@Autowiredunless there’s a specific reason - Stick to one style across your codebase for consistency
