连载中 11/18

@Autowired 与 @Resource:注入的门道

2026-11-07 · 43 阅读 · 0 评论 · 0 赞

一个接口两个实现,启动直接炸给你看

场景复刻:PayService 接口下面有 AliPayService 和 WechatPayService 两个实现,各自标了 @Service。这时在任何地方注入 PayService,启动瞬间就是 NoUniqueBeanDefinitionException——按类型找到了两个候选,Spring 不知道该注哪个。这不是 bug,是注入规则的必然结果。想把这类问题一网打尽,得先分清两个注入注解的身世。

byType 与 byName:底层分野

@Autowired 是 Spring 家的注解,默认按类型注入:先按类型找 Bean,唯一则直接注入;找到多个候选,就退而求其次把字段名当 Bean 名字去匹配;还匹配不上才抛异常。@Resource 是 JSR-250 标准注解(Boot 3 里在 jakarta.annotation 包下),默认按名称注入:先拿字段名当 Bean 名找,找不到再退回按类型。一句话记住:Autowired 先看类型,Resource 先看名字。

@Service
public class AliPayService implements PayService { }

@Service
public class WechatPayService implements PayService { }

// @Autowired:按类型两个候选 → 按字段名 aliPayService 匹配 → 命中
@Autowired
private PayService aliPayService;

// @Resource:先找名字叫 alipay 的 Bean → 没有 → 退回按类型 → 两个 → 炸
@Resource
private PayService alipay;

多实现注入的三种正解

第一种 @Primary:标在其中一个实现类上,它成为同类型候选里的默认人选,其余场景照旧。第二种 @Qualifier:注入时点名,指名道姓不猜谜。第三种 @Resource(name):用 name 属性直接指定。三种都能解决,团队统一一种即可。

// 方案一:谁当默认,谁标 @Primary
@Primary
@Service
public class AliPayService implements PayService { }

// 方案二:@Autowired 配 @Qualifier 点名
@Autowired
@Qualifier("wechatPayService")
private PayService payService;

// 方案三:@Resource 指定 name
@Resource(name = "wechatPayService")
private PayService payService;

字段、setter、构造器:官方为什么推构造器

字段注入最省事,代价也清楚:字段没法标 final;脱离容器就没法构造——单测里 new 出来的对象依赖全是 null,只能靠反射硬塞;类和容器焊死。构造器注入是 Spring 官方推荐:依赖可以 final 保证不可变;依赖摆在构造参数里一目了然,参数膨胀到七八个时,代码自己就在喊「职责太重」;单测直接 new 传 mock,零反射。setter 注入留给可选依赖。另外从 Spring 4.3 起,只有一个构造器的类连 @Autowired 注解都能省。

@Service
public class OrderService {

    private final PayService payService; // final:构造后不可变

    // Spring 4.3+ 单构造器自动注入,注解可省
    public OrderService(PayService payService) {
        this.payService = payService;
    }
}

别忘了,注进来的是代理

呼应 AOP 那两篇:有切面、有事务的 Bean,@Autowired 注进来的其实是代理对象。所以别用反射往私有字段里硬塞对象,也别绕开容器自己 new——让容器来管,代理才能站好岗。再送一个冷知识:@Autowired 有个 required = false 属性,容器里没有这个 Bean 也不报错;更优雅的玩法是 ObjectProvider,它下一篇循环依赖里还要出场。

下一篇拆注入的经典事故:循环依赖。Boot 2.6 为什么默认禁止?@Lazy 能救哪些,构造器注入为什么是无解的死结?

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#Spring#依赖注入#Autowired#Qualifier

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10134 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9899 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9329 阅读 · 21 评论 · 287 赞