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

spring 依赖注入的好处

spring框架通过依赖注入,对象之间的依赖关系由 Spring 容器来管理,而不是在代码中硬编码。

这意味着一个类不再需要自己创建和管理其依赖的对象,而是由 Spring 容器将依赖的对象注入到类中

例如:

在一个用户管理系统中,UserService 类依赖于 UserDao 类,使用 Spring 的依赖注入,UserService 类不需要在内部使用 new 关键字创建 UserDao 的实例,而是由 Spring 容器将 UserDao 的实例注入到 UserService 中。这样,UserService 与 UserDao 的实现细节解耦,当 UserDao 的实现发生变化时,UserService 类不需要进行修改。

场景一:更换 UserDao 的实现类

原理

Spring 的自动注入基于依赖倒置原则,让 UserService 依赖于抽象(接口)而非具体实现当需要更换 UserDao 实现类时,只需在 Spring 的配置中调整注入的具体实现类,而 UserService 类本身依赖的是抽象接口,不会受到实现类更换的影响。

代码示例

1. 定义 UserDao 接口
// UserDao 接口,定义用户数据访问的方法
public interface UserDao {
    void saveUser();
}
2. 实现 UserDao 接口
// 旧的 UserDao 实现类
import org.springframework.stereotype.Repository;

@Repository
public class OldUserDao implements UserDao {
    @Override
    public void saveUser() {
        System.out.println("使用旧方法保存用户信息");
    }
}

// 新的 UserDao 实现类
import org.springframework.stereotype.Repository;

@Repository
public class NewUserDao implements UserDao {
    @Override
    public void saveUser() {
        System.out.println("使用新方法保存用户信息");
    }
}
3. 定义 UserService 类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private UserDao userDao;

    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

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

在 UserService 类中,构造函数通过 @Autowired 注解注入 UserDao 接口的实现类。UserService 只依赖于 UserDao 接口,不关心具体是哪个实现类。

4. Spring 配置类(使用 Java 配置)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    // 这里可以选择注入旧的实现类
    // @Bean
    // public UserDao userDao() {
    //     return new OldUserDao();
    // }

    // 也可以选择注入新的实现类
    @Bean
    public UserDao userDao() {
        return new NewUserDao();
    }

    @Bean
    public UserService userService(UserDao userDao) {
        return new UserService(userDao);
    }
}

场景二:UserDao 构造函数发生变化

代码示例

首先,我们有一个简单的 UserDao 类和 UserService 类,UserService 类手动创建 UserDao 实例。

// UserDao 类,用于处理用户数据访问
class UserDao {
    public UserDao() {
        System.out.println("UserDao 实例被创建");
    }

    public void saveUser() {
        System.out.println("保存用户信息");
    }
}

// UserService 类,用于处理用户业务逻辑,依赖于 UserDao
class UserService {
    private UserDao userDao;

    public UserService() {
        this.userDao = new UserDao();
    }

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

// 测试类
public class Main {
    public static void main(String[] args) {
        UserService userService = new UserService();
        userService.createUser();
    }
}

在这个初始代码中,UserService 类的构造函数里手动使用 new 关键字创建了 UserDao 实例。

构造函数变化

现在,假设 UserDao 的需求发生了变化,需要在构造函数中传入一个数据库连接字符串。

// 修改后的 UserDao 类,构造函数需要传入数据库连接字符串
class UserDao {
    private String dbConnectionString;

    public UserDao(String dbConnectionString) {
        this.dbConnectionString = dbConnectionString;
        System.out.println("UserDao 实例被创建,使用数据库连接字符串: " + dbConnectionString);
    }

    public void saveUser() {
        System.out.println("使用 " + dbConnectionString + " 保存用户信息");
    }
}

// UserService 类,由于 UserDao 构造函数变化,需要修改
class UserService {
    private UserDao userDao;

    public UserService() {
        // 这里需要修改,因为 UserDao 构造函数发生了变化
        this.userDao = new UserDao("jdbc:mysql://localhost:3306/mydb");
    }

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

// 测试类
public class Main {
    public static void main(String[] args) {
        UserService userService = new UserService();
        userService.createUser();
    }
}

可以看到,由于 UserDao 的构造函数发生了变化,UserService 类的构造函数也必须进行修改,这就体现了 UserService 与 UserDao 实现细节的紧密耦合。

相关文章:

  • vscode远程连接树莓派报错> Host key verification failed.> 过程试图写入的管道不存在。
  • mysql-innodb_autoinc_lock_mode=2 和innodb_autoinc_lock_mode=1可能引发的问题
  • CISP-PTE WEB题通关记录
  • 基于Kubeadm实现K8S集群扩缩容指南
  • 第十一届 蓝桥杯 嵌入式 省赛
  • cache更新策略
  • Redis Java 客户端 之 Jedis
  • BERT 模型是什么
  • SQL ​​主键(Primary Key)
  • 什么是具身智能?其发展五大趋势预测
  • 【C++游戏引擎开发】第12篇:GLSL语法与基础渲染——从管线结构到动态着色器
  • 循环神经网络 - 长短期记忆网络的门控机制
  • [原创](现代C++ Builder 12指南): 如何使用异常(try catch)?
  • 从 SaaS 到 MCP:构建 AI Agent 生态的标准化服务升级之路
  • 基于微信小程序的校园跑腿系统的设计与实现
  • MV-DLS600P激光振镜立体相机(MV-DLS600P)重要参数解析
  • Linux 守护进程浅析
  • RK3588 android12 适配 ilitek i2c接口TP
  • FlinkSQL的常用语言
  • C++20 统一容器擦除:std::erase 和 std::erase_if
  • 唐山医疗网站建设/哔哩哔哩推广网站
  • 网站关键词设置技巧/东莞日增感染人数超25万
  • app平台运营模式/网站优化关键词
  • 济宁网站建设多少钱/如何写市场调研报告
  • 商城模板建站/收录是什么意思
  • 阿里云自己做网站/一个企业该如何进行网络营销