@Autowired`和 @Resource区别

@Autowired@Resource 是 Spring 中最常用的两个依赖注入注解,核心作用都是帮你从 Spring 容器中获取并注入所需的 Bean,但二者的设计来源、注入规则、使用方式有显著区别。下面我会从核心差异、使用场景、常见问题等方面,用通俗易懂的方式讲清楚它们的区别和用法。

一、核心区别(先看关键对比)

特性 @Autowired @Resource
来源 Spring 框架自带注解 JDK 自带注解(JSR-250 规范)
注入依据 优先按 类型(Type) 匹配 优先按 名称(Name) 匹配
支持的参数 required(是否必须注入)、qualifier(指定名称) name(指定名称)、type(指定类型)
支持的注入位置 字段、构造方法、setter 方法、方法参数 字段、setter 方法
默认值处理 默认 required=true,找不到 Bean 抛异常 默认 name 为字段名,找不到才按类型

二、@Autowired 详解

1. 基本用法(按类型注入)

@Autowired 核心逻辑是先按类型匹配,如果容器中只有一个该类型的 Bean,直接注入;如果有多个同类型 Bean,会尝试按字段名/方法名匹配 Bean 名称,匹配不到则抛异常。

@Service
public class UserService {
    // 按类型注入 UserDao 类型的 Bean
    @Autowired
    private UserDao userDao; 

    // 注入到构造方法(Spring 4.3+ 后,单个构造方法可省略 @Autowired)
    @Autowired
    public UserService(RoleService roleService) {
        this.roleService = roleService;
    }

    // 注入到 setter 方法
    @Autowired
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }
}

2. 解决多类型 Bean 冲突(@Qualifier)

当容器中有多个同类型 Bean 时,仅用 @Autowired 会报错,需配合 @Qualifier 指定 Bean 名称:

// 定义两个同类型 Bean
@Repository("userDaoImpl1")
public class UserDaoImpl1 implements UserDao {}

@Repository("userDaoImpl2")
public class UserDaoImpl2 implements UserDao {}

// 注入时指定名称
@Service
public class UserService {
    // 按类型找到两个 UserDao,通过 @Qualifier 指定名称注入
    @Autowired
    @Qualifier("userDaoImpl1") 
    private UserDao userDao;
}

3. 非必须注入(required=false)

默认 required=true,找不到 Bean 会抛 NoSuchBeanDefinitionException;设置 required=false 后,找不到则注入 null

@Service
public class UserService {
    // 找不到 RedisService 则注入 null,不会报错
    @Autowired(required = false)
    private RedisService redisService;
}

三、@Resource 详解

1. 基本用法(按名称注入)

@Resource 核心逻辑是先按名称匹配(默认名称是字段名/setter 方法名),找不到再按类型匹配;如果有多个同类型 Bean 且未指定名称,会抛异常。

@Service
public class UserService {
    // 1. 默认按名称 "userDao" 找 Bean,找不到再按类型 UserDao 找
    @Resource
    private UserDao userDao;

    // 2. 手动指定名称 "userDaoImpl1",精准注入
    @Resource(name = "userDaoImpl1")
    private UserDao userDao;

    // 3. 手动指定类型,仅按类型注入(不推荐,失去 @Resource 优势)
    @Resource(type = UserDaoImpl2.class)
    private UserDao userDao;
}

2. 解决多类型 Bean 冲突

直接通过 name 参数指定 Bean 名称即可,无需额外注解(比 @Autowired + @Qualifier 更简洁):

@Service
public class UserService {
    @Resource(name = "userDaoImpl2")
    private UserDao userDao; // 精准注入 UserDaoImpl2
}

四、使用场景建议

  1. 优先用 @Resource

    • 场景:需要按名称精准注入、代码需要兼容非 Spring 框架(如 JBoss)、不想写额外的 @Qualifier
    • 优势:语法简洁,按名称注入更直观,是 JDK 标准注解,耦合度更低。
  2. 优先用 @Autowired

    • 场景:需要注入到构造方法/方法参数、依赖 Spring 特有功能(如 @Autowired + @Value 注入配置)、想强制按类型注入;
    • 优势:Spring 原生支持,注入位置更灵活,配合 @Qualifier 可实现更细粒度控制。

五、常见坑点

1. @Autowired 注入 null

  • 原因:Bean 未被 Spring 管理(如没加 @Service/@Repository)、required=true 但找不到匹配 Bean、循环依赖未处理;
  • 解决:检查 Bean 注解、设置 required=false、排查循环依赖。

2. @Resource 按名称注入失败

  • 原因:指定的 name 与容器中 Bean 名称不匹配(Spring 中 Bean 名称默认是类名首字母小写,如 UserDaoImpluserDaoImpl);
  • 解决:核对 Bean 名称,或用 @Resource(type = Xxx.class) 按类型兜底。

3. 循环依赖

  • 现象:A 注入 B,B 注入 A,启动时报错;
  • 解决:@Autowired 支持字段注入的循环依赖(Spring 三级缓存处理),@Resource 同理;避免构造方法注入的循环依赖(构造方法注入不支持循环依赖)。

总结

  1. @Autowired 是 Spring 原生注解,优先按类型注入,需配合 @Qualifier 解决多 Bean 冲突,注入位置更灵活;
  2. @Resource 是 JDK 标准注解,优先按名称注入,语法更简洁,无需额外注解即可指定 Bean 名称,兼容性更好;
  3. 日常开发中,按名称注入用 @Resource,按类型注入/构造方法注入用 @Autowired,可根据场景灵活选择。
posted @ 2026-03-12 10:21  七星6609  阅读(11)  评论(0)    收藏  举报