@Resource 默认按名称注入,找不到时回退按类型匹配;支持name属性精准指定Bean名,不支持构造器注入,依赖Spring后置处理器生效。

@Resource 是 Java EE 标准注解(javax.annotation.Resource),Spring 完全支持,使用时默认按名称(byName)注入,找不到同名 Bean 时再回退按类型(byType)匹配。它不依赖 Spring 特有生态,兼容性好,写法也更直观。
基础用法:不指定 name,靠字段名自动匹配
Spring 会把字段名当作 bean 名去容器中查找:
- 比如字段声明为
@Resource private UserDao userDao;,Spring 就尝试找名为userDao的 Bean - 若存在
@Repository("userDao")或默认命名的UserDaoImpl(首字母小写为userDaoImpl),则注入成功 - 若没找到
userDao这个名字,再按UserDao类型搜索——但此时必须有且仅有一个匹配类型,否则报错
精准控制:显式指定 name 属性
当字段名和目标 Bean 名不一致,或想明确指向某个实现时,直接写 name:
@Resource(name = "userDaoMysql") private UserDao userDao;- 对应配置可以是:
@Repository("userDaoMysql") public class UserDaoMysqlImpl implements UserDao { ... } - 这种方式跳过类型匹配,只认名字;名字不存在就直接失败,不会降级尝试 byType
配合多实现接口的常见场景
一个接口有多个实现类时,@Resource 比 @Autowired 更省事,不用额外加 @Qualifier:
- 定义两个实现:
@Service("smsSender") public class SmsSenderImpl implements MessageSender { ... }和@Service("emailSender") public class EmailSenderImpl implements MessageSender { ... } - 注入时直接写:
@Resource(name = "smsSender") private MessageSender sender;,清晰无歧义 - 如果只写
@Resource private MessageSender sender;,则要求容器中必须有且仅有一个名为sender的 Bean;否则 fallback 到类型匹配,而类型匹配又会因多个实现失败
注意事项
几个容易踩坑的关键点:
-
@Resource不能用于构造方法注入(Spring 不支持),只能用于字段或 setter 方法 - 字段名作为默认 name 时,注意 Spring 默认 Bean 名是类名首字母小写,不是简单截取接口名或变量前缀
- 如果用了 Lombok 的
@RequiredArgsConstructor,别在构造器参数上误用@Resource,它不起作用 - 在非 Spring 管理的类(如 new 出来的对象)里加
@Resource注解,不会生效——它依赖 Spring 的后置处理器(CommonAnnotationBeanPostProcessor)处理


















