学静思语
Published on 2025-03-15 / 15 Visits
0
0

一、@Autowired和@Resource注解比较

Spring依赖注入与Java规范详解

一、@Autowired和@Resource注解比较

1.1 基本区别

| 特性 | @Autowired | @Resource |
| ——– | ——————————————– | ————————————– |
| 来源 | Spring框架 | JSR-250规范 |
| 包名 | org.springframework.beans.factory.annotation | javax.annotation |
| 注入方式 | 默认按类型(byType) | 默认按名称(byName),名称未指定时按类型 |
| 解决冲突 | 需结合@Qualifier使用 | 直接通过name属性指定 |
| 其他特性 | 有required属性可设置非必须依赖 | 具有更好的可移植性 |
| 使用位置 | 构造函数、字段、方法、参数 | 字段、方法 |

1.2 使用示例

@Autowired使用示例

// 按类型注入
@Autowired
private UserService userService;

// 配合@Qualifier解决多个相同类型bean的冲突
@Autowired
@Qualifier("mysqlUserDao")
private UserDao userDao;

// 设置为非必须依赖
@Autowired(required = false)
private OptionalService optionalService;

@Resource使用示例

// 默认按名称注入
@Resource
private UserService userService;

// 明确指定名称
@Resource(name = "mysqlUserDao")
private UserDao userDao;

二、JSR规范概述

2.1 JSR基本概念

  • 定义:JSR(Java Specification Request,Java规范提案)是为Java平台添加新特性和技术的正式规范文档
  • 目的:确保Java技术的标准化、兼容性和可移植性
  • 组织方式:由JCP(Java Community Process,Java社区进程)管理,专家组负责规范的制定和审核
  • 生命周期:提案→早期草案→公开审阅→最终发布→维护

2.2 JSR的重要性

  1. 标准化:为Java技术提供统一标准,避免技术碎片化
  2. 兼容性:确保不同厂商的Java实现能够相互兼容
  3. 开放性:允许社区参与Java平台的发展和演进
  4. 技术发展:推动Java技术的创新和进步

2.3 重要的JSR规范示例

  • JSR-175:Java注解(Annotations)规范
  • JSR-250:Common Annotations(包含@Resource等注解)
  • JSR-303/JSR-349:Bean Validation规范
  • JSR-330:依赖注入标准规范(@Inject等)
  • JSR-317/JSR-338:JPA(Java Persistence API)规范
  • JSR-365:CDI(Contexts and Dependency Injection)规范
  • JSR-370:JAX-RS(Java API for RESTful Web Services)

三、@Resource注解与JSR-250规范

3.1 JSR-250规范概述

  • 名称:Common Annotations for the Java Platform(Java平台通用注解)
  • 目的:为Java SE和Java EE平台开发一系列通用语义概念的注解,这些注解适用于多种技术
  • 初始版本:JSR-250在Java EE 5中首次引入
  • 当前版本:目前最新版本为1.2版
  • 现状:现已成为Jakarta EE项目的一部分,重命名为Jakarta Annotations

3.2 JSR-250中的主要注解

JSR-250规范不仅定义了@Resource注解,还定义了其他几个重要的通用注解:

  1. @Resource:用于资源注入
  2. @PostConstruct:标记实例构造后要调用的方法
  3. @PreDestroy:标记实例销毁前要调用的方法
  4. @Resources:用于声明多个@Resource注解
  5. @Generated:标记由工具生成的源代码
  6. @RunAs:安全角色相关
  7. @DeclareRoles:声明安全角色
  8. @RolesAllowed:访问控制注解
  9. @PermitAll:允许所有角色访问
  10. @DenyAll:拒绝所有角色访问

3.3 @Resource注解用途

@Resource注解主要用于将各种类型的资源注入到Java类中,包括:

  • 数据源(DataSource)
  • JMS连接工厂和目的地
  • 环境条目
  • EJB引用
  • Web服务引用等

它在企业应用中广泛用于依赖注入,特别是在Java EE环境中。

3.4 在Java EE和Spring中的应用

  • 在Java EE环境中,@Resource是标准的资源注入方式
  • 在Spring框架中,虽然有自己的@Autowired注解,但Spring也支持JSR-250规范中的@Resource注解,这体现了Spring对Java标准的兼容性

四、@Autowired注入优先级详解

4.1 基本注入优先级规则

@Autowired 注入遵循以下优先级顺序:

  1. 按类型匹配(默认行为)
  2. 使用 @Qualifier 指定名称
  3. 使用 @Primary 标记首选 bean
  4. 变量名称与 bean 名称匹配
  5. 构造器 > 方法 > 字段 (注入点优先级)

4.2 按类型注入详解

当使用 @Autowired 且不指定任何额外条件时,Spring 首先尝试按类型匹配:

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository; // 寻找类型为 UserRepository 的 bean
}

如果容器中只有一个 UserRepository 类型的 bean,则直接注入。

4.3 多个同类型 bean 的处理

当容器中存在多个相同类型的 bean 时,Spring 按以下顺序解决冲突:

4.3.1 @Primary 注解优先

@Repository
@Primary
public class MySQLUserRepository implements UserRepository {
    // 实现...
}

@Repository
public class MongoUserRepository implements UserRepository {
    // 实现...
}

此例中,自动注入时 MySQLUserRepository 将被优先选择。

4.3.2 @Qualifier 指定名称

@Qualifier 具有比 @Primary 更高的优先级:

@Repository("mongoRepo")
public class MongoUserRepository implements UserRepository {}

@Repository
@Primary
public class MySQLUserRepository implements UserRepository {}

@Service
public class UserService {
    @Autowired
    @Qualifier("mongoRepo")
    private UserRepository userRepository; // 将注入 MongoUserRepository
}

4.3.3 变量名匹配

当没有 @Qualifier 和 @Primary 时,变量名与 bean 名称匹配:

@Repository
public class MySQLUserRepository implements UserRepository {}

@Repository
public class MongoUserRepository implements UserRepository {}

@Service
public class UserService {
    @Autowired
    private UserRepository mongoUserRepository; // 将注入 MongoUserRepository
}

4.4 注入点优先级

Spring 在处理同一个类中多个注入点时的优先级顺序:

  1. 构造器注入:最高优先级,推荐用于必需依赖
  2. setter 方法注入:次优先级
  3. 字段注入:最低优先级
@Service
public class ComplexService {
    private final MainRepository mainRepository;

    @Autowired // 构造器注入优先执行
    public ComplexService(MainRepository mainRepository) {
        this.mainRepository = mainRepository;
    }

    @Autowired // 其次执行方法注入
    public void setHelper(HelperService helperService) {
        this.helperService = helperService;
    }

    @Autowired // 最后执行字段注入
    private OptionalService optionalService;
}

4.5 集合与数组注入

当字段类型为集合或数组时,Spring 会收集所有匹配类型的 bean:

@Service
public class AggregateService {
    @Autowired
    private List<PaymentProcessor> processors; // 注入所有 PaymentProcessor 类型的 bean

    @Autowired
    private Map<String, PaymentProcessor> processorMap; // 注入所有 PaymentProcessor 以bean名为key
}

4.6 实际应用建议

  1. 优先使用构造器注入:使依赖关系明确且不可变
  2. 对必需依赖使用 final 字段:防止依赖被修改
  3. 对可选依赖使用 @Autowired(required=false):避免找不到 bean 时抛出异常
  4. 在有多个同类型 bean 时使用明确的 @Qualifier:提高代码可读性和可维护性
  5. 慎用 @Primary:可能在大型项目中导致意外行为

五、Spring框架与JSR规范的关系

Spring框架实现了许多JSR规范,如:

  • 依赖注入规范(JSR-330)
  • Common Annotations(JSR-250,包括@Resource注解)
  • Bean Validation(JSR-303)

同时,Spring也提供了自己的扩展和实现,比如@Autowired注解,以提供更加丰富和灵活的功能。Spring框架的设计理念是尽可能地与Java标准兼容,同时提供更强大的功能和更好的开发体验。


Comment