当前位置: 首页 > news >正文

Spring IOC/DI的依赖注入方式及示例

Spring IOC/DI的依赖注入方式及示例

Spring的依赖注入(DI)支持多种方式,以下是核心方式及示例:


1. 构造器注入(Constructor Injection)

通过构造函数传递依赖,确保依赖在对象初始化时存在,推荐用于必填依赖。

示例代码:
// 依赖接口
public interface UserDao {
    void save();
}

// 依赖实现
@Component
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("User saved");
    }
}

// 服务类(通过构造函数注入)
@Service
public class UserService {
    private final UserDao userDao;

    // 使用 @Autowired 的构造函数注入
    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public void createUser() {
        userDao.save();
    }
}

注释说明

  • @Autowired 标注构造函数,Spring会自动注入 UserDao 的实现。
  • userDao 被标记为 final,确保不可变性。

2. 字段注入(Field Injection)

直接在字段上使用 @Autowired,由Spring自动注入,代码简洁但需谨慎使用。

示例代码:
// 依赖接口和实现与上同

// 服务类(通过字段注入)
@Service
public class UserService {
    @Autowired // 直接在字段上标注
    private UserDao userDao;

    public void createUser() {
        userDao.save();
    }
}

注释说明

  • 字段直接标注 @Autowired,无需构造函数或Setter方法。
  • 缺点:可能绕过对象初始化逻辑,字段可能为 null(如延迟加载)。

3. Setter方法注入(Setter Injection)

通过Setter方法注入依赖,支持可选依赖或动态修改。

示例代码:
// 依赖接口和实现与上同

// 服务类(通过Setter注入)
@Service
public class UserService {
    private UserDao userDao;

    // 使用 @Autowired 的Setter方法
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void createUser() {
        userDao.save();
    }
}

注释说明

  • 依赖通过Setter方法注入,支持可选依赖(如 @Autowired 可标记为 required=false)。

4. @Value 注入基本类型或SpEL表达式

用于注入配置属性(如字符串、数字)或表达式。

示例代码:
@ConfigurationProperties(prefix = "app.config")
@Component
public class AppConfig {
    private String databaseUrl;
    private int timeout;

    // getters/setters
}

// 服务类(通过 @Value 注入)
@Service
public class DatabaseService {
    @Value("${app.config.databaseUrl}") // 从配置文件读取
    private String databaseUrl;

    @Value("#{ T(java.lang.Math).random() * 100 }") // SpEL表达式
    private double randomValue;

    public void printConfig() {
        System.out.println("Database URL: " + databaseUrl);
        System.out.println("Random Value: " + randomValue);
    }
}

注释说明

  • @Value 支持直接注入配置文件属性(如 application.properties)或表达式。

5. @Qualifier 解决依赖歧义

当存在多个相同类型的Bean时,通过 @Qualifier 指定具体Bean。

示例代码:
// 两个相同接口的Bean
@Component
@Qualifier("primary")
public class PrimaryUserDao implements UserDao {
    public void save() { System.out.println("Primary DAO"); }
}

@Component
@Qualifier("secondary")
public class SecondaryUserDao implements UserDao {
    public void save() { System.out.println("Secondary DAO"); }
}

// 服务类(通过 @Qualifier 指定Bean)
@Service
public class UserService {
    @Autowired
    @Qualifier("primary") // 指定使用PrimaryUserDao
    private UserDao userDao;

    public void createUser() {
        userDao.save();
    }
}

对比表格

方式优点缺点适用场景
构造器注入- 依赖必填,确保初始化完成
- 支持 final 字段
- 测试友好
- 代码冗余(需写构造函数)推荐:必填依赖、复杂对象初始化、测试驱动开发(TDD)
字段注入- 简单快捷- 可能绕过构造函数逻辑
- 字段可能未初始化(null
快速开发、简单场景(非核心依赖)
Setter注入- 灵活支持可选依赖- 依赖可能延迟注入
- 难以保证线程安全
可选依赖、动态修改依赖场景(如配置类)
@Value 注入- 直接注入配置属性或表达式- 仅限简单类型(需配合 @ConfigurationProperties 处理复杂配置)配置参数注入(如数据库URL、常量)
@Qualifier 解歧义- 明确指定Bean,解决类型冲突- 需额外标注,增加代码复杂度多个同类型Bean共存时选择具体实现

选择建议

  1. 优先使用构造器注入:确保依赖存在且易于测试。
  2. 字段注入:仅在简单场景或快速开发时使用。
  3. Setter注入:用于可选依赖或需要后期绑定的场景。
  4. @Value + @ConfigurationProperties:集中管理配置属性。
  5. @Qualifier:解决依赖冲突时明确指定Bean。

相关文章:

  • 索引(重点)
  • 地理信息可视化技术大全【WebGIS 技术文档大全】
  • 科大讯飞语音转文字STT--unity
  • mysql死锁排查解决
  • Mysql 回表查询,什么是回表查询,如何拒绝sql查询时的回表问题
  • 【Django】教程-3-数据库相关介绍
  • C++中的判断与循环
  • Python 魔术方法功能分类指南
  • 十一、JavaScript简单数据类型和复杂数据类型
  • 材料科学基础:空间群与点群(1)
  • flutter 获取设备的唯一标识
  • 数仓开发那些事(11)
  • chrome-driver安装
  • 【商城实战(77)】商城智能客服系统搭建指南:选型与集成全攻略
  • 大模型有哪些算法
  • 注释容易混淆?修改vscode注释颜色,自定义你的专属颜色
  • Spring Cloud Kubernetes :云原生与容器化部署实战
  • SpringMVC实战——转发和重定向及实际场景
  • Linux中磁盘的管理
  • 对人工智能祛魅了
  • 建设电子商务网站的规划书/搜狗收录提交
  • 大学网站建设专业/网络营销的特点分别是
  • 生产企业展厅设计/seo公司排名教程
  • 深圳建设网站培训机构/网站推广排名哪家公司好
  • .net 网站开发实例/域名注册管理机构
  • 自己做网站需要什么材料/线上推广产品