JSR 330 (Java Specification Request 330)是 Java 平台中一项关于 依赖注入(Dependency Injection, DI) 的标准化规范,全称为:
Dependency Injection for Java
它由 Java Community Process(JCP)于 2009 年正式发布,旨在为 Java 应用定义一套通用、可移植的依赖注入注解标准,使代码不依赖于特定框架(如 Spring、Guice),从而提升模块化、可测试性和可维护性。
一、核心目标
- ✅ 标准化 DI 注解:让不同 DI 框架(Spring、Guice、CDI 等)使用相同的注解。
- ✅ 解耦业务代码与框架 :开发者只需依赖
javax.injectAPI,无需绑定具体实现。 - ✅ 简化单元测试:通过构造函数或 setter 注入,便于 mock 依赖。
二、JSR 330 定义的核心注解(位于 javax.inject 包)
| 注解 | 作用 | 对应 Spring 注解 |
|---|---|---|
@Inject |
标记需要注入的字段、方法或构造函数 | @Autowired |
@Named |
为 Bean 提供名称,用于区分多个实现 | @Component("name") 或 @Qualifier("name") |
@Singleton |
声明该类为单例(仅在支持的作用域中有效) | @Scope("singleton")(但功能有限) |
Provider<T> |
延迟获取或多次获取依赖实例(类似工厂) | ObjectFactory<T> |
⚠️ 注意:JSR 330 只定义注解和基本语义,不提供容器实现。具体行为由 DI 框架(如 Spring)实现。
三、使用示例
1. 定义服务接口与实现
java
// 接口
public interface MessageService {
String getMessage();
}
// 实现类(使用 @Named 指定名称)
@Named("email")
public class EmailService implements MessageService {
public String getMessage() {
return "Email message";
}
}
2. 使用 @Inject 注入依赖
java
public class MessageProcessor {
private final MessageService service;
// 构造函数注入
@Inject
public MessageProcessor(@Named("email") MessageService service) {
this.service = service;
}
public void process() {
System.out.println(service.getMessage());
}
}
3. 在 Spring 中启用 JSR 330
需添加依赖(Maven):
xml
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
然后配合 @ComponentScan 自动注册 @Named 类为 Bean。
四、JSR 330 vs Spring 原生注解
| 特性 | JSR 330 (javax.inject) |
Spring (org.springframework.stereotype) |
|---|---|---|
| 注入注解 | @Inject |
@Autowired |
| 可选注入 | ❌ 不支持 required=false✅ 需用 Optional<T> 或 @Nullable |
✅ @Autowired(required = false) |
| Bean 命名 | @Named("name") |
@Component("name") |
| 作用域控制 | 仅 @Singleton(语义弱) |
@Scope("prototype")、@RequestScope 等完整支持 |
| 扩展性 | ❌ 不能派生自定义注解(如 @Service) |
✅ 可基于 @Component 创建 @Service, @Repository 等 |
📌 Spring 完全兼容 JSR 330 ,但推荐在 Spring 项目中优先使用 Spring 原生注解(功能更强大);若开发跨框架库,则使用 JSR 330 更具可移植性。
五、典型应用场景
- 开发 第三方库或 SDK,希望不强制用户使用特定 DI 框架
- 构建 模块化系统,各模块通过标准注解解耦
- 提升代码 可测试性 (
@Inject支持构造函数注入,利于单元测试)
六、局限性
- 不支持可选注入 (无
required=false) - 作用域支持有限 :
@Singleton仅表示"单例",无法表达prototype、request等作用域 - 无法自定义语义化注解 :不能像 Spring 那样定义
@MyService - 生命周期回调缺失 :如
@PostConstruct属于 JSR 250,非 JSR 330 范畴
💡 实际开发中,常 混合使用 JSR 330 + JSR 250 (如
@Inject+@PostConstruct)
七、总结
| 项目 | 内容 |
|---|---|
| JSR 编号 | 330 |
| 规范名称 | Dependency Injection for Java |
| 核心价值 | 提供标准、可移植的依赖注入注解 |
| 关键注解 | @Inject, @Named, @Singleton, Provider<T> |
| 适用场景 | 跨框架库、标准化组件、高可测试性需求 |
| 依赖包 | javax.inject:javax.inject:1 |
🔗 JSR 330 是 Java DI 生态的"通用语言" ------ 虽然功能不如 Spring 原生注解丰富,但它是实现框架无关性的关键一步。
官方 Javadoc(规范仅以 API 形式发布):