Spring依赖注入注解详解:@Autowired、@Resource、@Inject

Spring依赖注入注解详解:@Autowired、@Resource、@Inject


一、注解概览

注解 所属标准 装配方式 是否支持required 包路径
@Autowired Spring原生 类型优先,支持名称 支持 org.springframework.beans.factory.annotation
@Resource JSR-250 名称优先,支持类型 不支持 javax.annotation
@Inject JSR-330 类型优先,支持名称 不支持 javax.inject

二、核心原理剖析

1. @Autowired

  • 处理器:AutowiredAnnotationBeanPostProcessor
  • 装配流程
    1. 根据类型查找候选Bean
    2. 使用@Qualifier或限定符缩小范围
    3. 按名称匹配(当找不到唯一类型时)
    4. 处理@Primary标注的Bean
    5. 处理泛型依赖

2. @Resource

  • 处理器:CommonAnnotationBeanPostProcessor
  • 解析策略
    • 未指定name时:按字段/方法名称查找
    • 指定name时:直接按名称查找,失败后回退到类型匹配

3. @Inject

  • 依赖:需引入javax.inject包
  • 实现机制
    • 类似@Autowired但无required属性
    • 配合@Named实现名称注入

三、使用场景与案例

1. 基础注入示例

java 复制代码
// @Autowired构造器注入(推荐)
@Service
public class OrderService {
    private final OrderRepository repository;
    
    @Autowired
    public OrderService(OrderRepository repository) {
        this.repository = repository;
    }
}

// @Resource字段注入
@Repository
public class UserDao {
    @Resource(name = "secondaryDataSource")
    private DataSource dataSource;
}

// @Inject方法注入
@Component
public class PaymentProcessor {
    private GatewayService gateway;
    
    @Inject
    public void setGateway(@Named("wechat") GatewayService gateway) {
        this.gateway = gateway;
    }
}

2. 特殊场景处理

多实现类选择:

java 复制代码
@Configuration
public class AppConfig {
    @Bean
    @Primary
    public Cache redisCache() {
        return new RedisCache();
    }

    @Bean
    @Qualifier("local")
    public Cache localCache() {
        return new LocalCache();
    }
}

@Service
public class CacheService {
    @Autowired  // 注入RedisCache
    private Cache cache;
    
    @Autowired
    @Qualifier("local")  // 明确指定
    private Cache localCache;
}

四、避坑指南

1. 常见异常及解决方案

  • NoSuchBeanDefinitionException
    • 检查组件扫描配置
    • 确认Bean是否被正确加载(@Component/@Bean)
  • NoUniqueBeanDefinitionException
    • 使用@Qualifier限定
    • 设置@Primary Bean
    • 显式指定Bean名称

2. 循环依赖问题

  • 症状:BeanCurrentlyInCreationException
  • 解决方案
    • 使用setter注入替代构造器注入
    • @Lazy延迟初始化
    • 重构代码结构

3. 作用域陷阱

java 复制代码
@Autowired
private RequestScopedBean bean; // 可能注入代理对象

五、最佳实践

  1. 注入方式优先级

    • 构造器注入 > Setter注入 > 字段注入
    • 强制依赖使用构造器注入,可选依赖使用Setter
  2. 注解选择策略

    • Spring项目首选@Autowired
    • 需要JSR标准支持时用@Resource/@Inject
    • 跨容器应用考虑@Resource
  3. 命名规范

    • 保持Bean名称一致性:
    java 复制代码
    @Service("userService")  // 显式命名
    public class UserServiceImpl implements UserService {}
    
    @Resource(name = "userService")  // 准确匹配
    private UserService service;
  4. 测试友好性

    • 使用构造器注入方便Mock测试
    java 复制代码
    @Test
    void testService() {
        UserRepository mockRepo = Mockito.mock(UserRepository.class);
        UserService service = new UserService(mockRepo);
        // 测试逻辑
    }

六、总结对比

维度 @Autowired @Resource @Inject
标准性 Spring特有 JSR-250 JSR-330
灵活性 高(支持required)
装配策略 类型优先 名称优先 类型优先
依赖 需javax.inject
适用场景 纯Spring项目 跨容器应用 标准Java项目

最终建议:单一框架项目优先使用@Autowired,需要标准化时根据场景选择@Resource/@Inject。保持代码的注入方式统一,合理使用限定符,避免过度依赖自动装配。


通过本文的解析,读者可以全面掌握Spring核心依赖注入注解的使用技巧,避免常见的配置陷阱,构建更健壮的应用程序。实际开发中应根据项目需求和团队规范灵活选择合适的注入策略。

相关推荐
javadaydayup1 小时前
明明说好的国际化,可你却还是返回了中文
spring boot·后端·spring
程序员秘密基地2 小时前
基于vscode,idea,java,html,css,vue,echart,maven,springboot,mysql数据库,在线考试系统
java·vue.js·spring boot·spring·web app
吾日三省吾码2 小时前
Spring 团队详解:AOT 缓存实践、JSpecify 空指针安全与支持策略升级
java·spring·缓存
花月C5 小时前
Mysql-定时删除数据库中的验证码
数据库·后端·mysql·spring
风铃儿~15 小时前
Spring AI 入门:Java 开发者的生成式 AI 实践之路
java·人工智能·spring
hstar952719 小时前
三十三、面向对象底层逻辑-SpringMVC九大组件之HandlerExceptionResolver接口设计
java·spring·设计模式·架构
面朝大海,春不暖,花不开19 小时前
Spring Security默认配置覆盖指南
java·后端·spring
IT_Octopus21 小时前
多线程下使用缓存+锁Lock, 出现“锁失效” + “缓存未命中竞争”的缓存击穿情况,双重检查缓存解决问题
java·spring·缓存
qq_338032921 天前
Spring Boot/Spring应用中配置自定义RedisTemplate
spring boot·redis·spring
考虑考虑1 天前
Springboot3.5.x版本actuator新属性
spring boot·后端·spring