@Autowired 和 @Resource 注解的区别?

#Java#面试八股

@Autowired 和 @Resource 注解的区别?

结论先行:@Autowired 是 Spring 自有注解,由 AutowiredAnnotationBeanPostProcessor 处理,默认按类型(byType)注入,找不到唯一候选时再按名称收敛,另有 required 开关;@Resource 是 JSR-250 标准注解,由 CommonAnnotationBeanPostProcessor 处理,默认按名称(byName)注入,名字取字段名或 name 属性,找不到才回退按类型。二者都是"依赖注入的语法糖",但解析策略、来源、可标注位置、缺省行为都不同。

一、逐项对比

维度@Autowired@Resource
规范来源Spring 专有(org.springframework.beans.factory.annotation)JSR-250(jakarta.annotation / 旧 javax.annotation)
后置处理器AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor
匹配策略先 byType,多个候选再按字段/参数名或 @Qualifier 收窄先 byName,按名字找不到才 byType
名字来源@Qualifier("x")、参数名、字段名name 属性 → 否则字段名
是否必需可 required=false,允许为 null无 required 属性,找不到就启动失败
可标注位置构造器、方法、参数、字段、注解字段、setter 方法、类(作为类级资源)
多实现时需 @Qualifier 或字段名匹配用 name 指定更直观
与 Spring 耦合高低,可替换实现

二、匹配过程

@Autowired 注入 UserService:
  ① 按类型找候选 → 命中 1 个:直接注入
                 → 命中 0 个:required=true 抛 NoSuchBeanDefinitionException
                 → 命中多个:用 @Qualifier / 字段名 / @Primary 收窄

@Resource(name="userService") 注入:
  ① 按名字找 → 命中:注入
             → 未命中:回退按类型找 → 命中 1 个:注入
                                  → 多个或 0 个:抛异常

三、代码对照

@Service
public class OrderService {

    // 推荐:构造器注入,字段 final,依赖显式、易于单测
    private final PayService payService;
    private final NotifyService notifyService;

    public OrderService(PayService payService,
                        @Qualifier("smsNotify") NotifyService notifyService) {
        this.payService = payService;
        this.notifyService = notifyService;   // 多个实现用 @Qualifier 收窄
    }

    // @Resource 适合"按 Bean 名取",比如策略实现按名字区分
    @Resource(name = "alipayStrategy")
    private PayStrategy alipay;

    // @Autowired 的 required=false:允许容器里没有这个 Bean
    @Autowired(required = false)
    private Optional<MetricsReporter> reporter;
}
// 同名多实现时的两种收窄写法
@Component("smsNotify")
public class SmsNotifyService implements NotifyService { }

@Component("mailNotify")
public class MailNotifyService implements NotifyService { }

@Resource(name = "mailNotify")        // 名字精确命中
private NotifyService notify;

四、什么时候选哪个

  • 项目已统一用 Spring 技术栈、依赖构造器注入 → 用 @Autowired(构造器上只有一个构造器时甚至可省略);
  • 需要按 Bean 名注入、或代码要尽量少依赖 Spring API → 用 @Resource;
  • 存在多实现且语义就是"选某个具名策略" → @Resource(name=...) 比 @Autowired + @Qualifier 更直白;
  • 三者混用时注意:@Autowired 与 @Resource 标在同一字段上,@Resource 生效(CommonAnnotationBeanPostProcessor 优先级更高)。

五、常见追问

  • 问:为什么推荐构造器注入? 依赖不可变(final)、启动即暴露缺失依赖、循环依赖会直接报错而不是靠三级缓存掩盖、单测无需容器。
  • 问:字段名参与匹配吗? 会。@Autowired 在多个候选时会退化用字段名/参数名匹配,这依赖编译时保留参数名(-parameters),所以别把它当稳定契约,显式 @Qualifier 更可靠。
  • 问:@Autowired 能注 List<T> 吗? 能,容器会注入所有 T 的实现,配合 @Order 可控制顺序,这是策略模式的常用写法。
  • 问:JDK 11 之后 @Resource 报找不到符号? Spring Boot 3 已切到 jakarta.annotation.Resource,老项目需显式引入 jakarta.annotation-api 或 javax.annotation-api。

小结

一句话区分:@Autowired 是"按类型找,多个再挑名字",@Resource 是"按名字找,找不到再看类型"。答题时补上处理器、来源、required、可标注位置四个维度,再说明"生产代码优先构造器注入",就不会被追问倒。

笔记加载中…