红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. 未分类
  3. 正文

@Autowired 和 @Resource 的区别

2025年5月20日 59点热度 0人点赞 0条评论

今天遇到一个奇怪的问题,在配置类中注册了一个拦截器:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Resource
    private AuthInterceptor authInterceptor;
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器,并指定拦截路径
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/**") // 拦截所有路径
                .excludePathPatterns("/login",
                        "/login/sendCode/*"); // 排除登录和注册接口
    }
}

这里的authInterceptor属性表示的拦截器使用@Resource进行注入。其定义:

@Component
public class AuthInterceptor implements HandlerInterceptor {
    private final RedisToken redisToken;
    private final UserService userService;
​
    public AuthInterceptor(RedisToken redisToken, UserService userService) {
        this.redisToken = redisToken;
        this.userService = userService;
    }
    // ...
}

使用构造器注入两个属性,构造器上的@Autowrired注解省略掉了。

看上去似乎没有问题,但实际编译就会遇到吊轨的事情,有时候能编译通过,有时候又不能,还会随着 JVM 版本的同步反复横跳。

但,如果在配置类中使用@Autowired注入,就不会有类似的问题。

因此就有了这篇文章,以下内容都是 DeepSeek 的马甲腾讯元宝生成的。

@Autowired 和 @Resource 都是用于依赖注入的注解,但它们在来源、匹配方式、默认行为等方面有显著区别。以下是详细对比和用法说明:


1. 来源与规范

注解 来源 规范
@Autowired Spring 框架提供 属于 Spring 特有的注解
@Resource Java 标准注解(JSR-250) 属于 Java EE(现 Jakarta EE)规范,Spring 也支持

注意:

  • @Resource 在 Java 9+ 中被标记为 @Deprecated(但仍可用),推荐使用 jakarta.annotation.Resource(Jakarta EE 8+)。

  • 如果项目使用纯 Spring 生态,优先用 @Autowired;如果需要跨框架兼容(如 Java EE),可用 @Resource。


2. 匹配方式

特性 @Autowired @Resource
默认匹配规则 按 类型(Type) 匹配 按 名称(Name) 匹配
支持按名称匹配 需配合 @Qualifier 使用 直接通过 name 或字段名匹配
多候选 Bean 时的行为 报错(需用 @Qualifier 指定) 报错(需确保名称唯一)

示例对比

java

复制

// 假设有两个相同类型的 Bean
@Service("userService1")
public class UserServiceImpl1 implements UserService {}
​
@Service("userService2")
public class UserServiceImpl2 implements UserService {}
(1) @Autowired + @Qualifier(按名称匹配)

java

复制

@Autowired
@Qualifier("userService1") // 明确指定要注入的 Bean 名称
private UserService userService;
(2) @Resource(按名称匹配)

java

复制

@Resource(name = "userService1") // 直接指定名称
private UserService userService;

或通过字段名匹配(默认按字段名查找 Bean):

java

复制

@Resource // 默认匹配名为 "userServiceImpl1" 的 Bean(需配合 @Service("userServiceImpl1"))
private UserService userService; // 字段名为 userService → 尝试匹配名为 "userService" 的 Bean

3. 是否支持非必需依赖

注解 是否支持 required=false 行为
@Autowired 支持 @Autowired(required = false) 表示依赖可选(找不到 Bean 时注入 null)
@Resource 不支持 如果找不到匹配的 Bean,直接抛出 NoSuchBeanDefinitionException

示例

java

复制

// @Autowired 允许可选依赖
@Autowired(required = false)
private OptionalDependency optionalDependency; // 找不到时注入 null
​
// @Resource 必须找到 Bean,否则报错
@Resource
private RequiredDependency requiredDependency; // 找不到时抛异常

4. 对集合类型的支持

注解 对 List/Map 的支持 行为
@Autowired 支持 自动注入所有匹配类型的 Bean(List<BeanType>)或按名称映射的 Map(Map<String, BeanType>)
@Resource 不支持直接注入集合 需通过 @Resource(name = "beanName") 逐个注入

示例

java

复制

// @Autowired 注入所有 UserService 实现
@Autowired
private List<UserService> userServiceList; // 包含 userService1 和 userService2
​
// @Resource 无法直接注入集合,需手动处理
@Resource(name = "userService1")
private UserService userService1;
​
@Resource(name = "userService2")
private UserService userService2;

5. 与构造函数/Setter 方法的配合

注解 构造函数注入 Setter 方法注入
@Autowired 支持(Spring 4.3+ 可省略 @Autowired) 支持
@Resource 不支持(仅支持字段或方法注入) 支持

示例

java

复制

// @Autowired 构造函数注入(Spring 4.3+ 可省略注解)
@Service
public class OrderService {
    private final UserService userService;
​
    public OrderService(UserService userService) { // 无需 @Autowired
        this.userService = userService;
    }
}
​
// @Resource 构造函数注入(不支持)
// 错误示例!@Resource 不能用于构造函数
//@Resource
//public OrderService(UserService userService) {}

6. 性能差异

  • @Autowired: Spring 原生注解,直接与 Spring 容器交互,性能略高(但差异可忽略)。

  • @Resource: 需通过反射调用 Java 标准注解机制,可能稍慢(实际场景中无显著影响)。


7. 如何选择?

场景 推荐注解
纯 Spring 项目 优先使用 @Autowired(更灵活,支持构造函数注入)
需要跨框架兼容 使用 @Resource(如 Java EE 环境)
按名称匹配依赖 两者均可,但 @Resource 更直观
可选依赖 必须用 @Autowired(required = false)
集合类型注入 必须用 @Autowired

8. 完整代码示例

场景:注入一个可选的 UserService

使用 @Autowired

java

复制

@Service
public class OrderService {
    private final UserService userService;
​
    @Autowired(required = false) // 可选依赖
    public OrderService(UserService userService) {
        this.userService = userService;
    }
}

使用 @Resource

java

复制

@Service
public class OrderService {
    private UserService userService;
​
    @Resource(required = false) // 错误!@Resource 不支持 required=false
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

注意:@Resource 不支持 required=false,需改用其他方式(如 @Nullable 或手动检查 null)。


9. 总结

特性 @Autowired @Resource
来源 Spring 特有 Java 标准(JSR-250)
匹配方式 默认按类型,可用 @Qualifier 按名称 默认按名称,也可按类型
可选依赖 支持(required=false) 不支持
集合注入 支持(List<Bean>/Map<String, Bean>) 不支持
构造函数注入 支持(Spring 4.3+ 可省略注解) 不支持
适用场景 纯 Spring 项目 跨框架兼容或需要按名称注入

推荐实践:

  • 优先用 @Autowired(功能更全面,与 Spring 生态集成更好)。

  • 仅在需要跨框架兼容时用 @Resource(如 Java EE 环境)。

  • 按名称注入时:两者均可,但 @Resource 更直观(直接通过 name 属性指定)。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: autowried spring
最后更新:2025年5月20日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

*

code

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号