别再懵圈了!Spring IOC/DI,看完不懂你喷我!

一、什么是IOC(控制反转)?

  • 传统方式: 想象一下,你要盖房子。传统方式是你自己找砖头、水泥、钢筋,自己搅拌水泥,自己一块一块地砌砖。所有的事情都由你来控制😥。

  • IOC 方式: 现在有了 IOC,你只需要告诉一个建筑公司(IOC 容器):"我要盖房子,需要这些材料和工人。" 建筑公司会帮你准备好一切,你只需要等着房子盖好就行了😎。你不再需要自己控制每一个细节,控制权交给了建筑公司。

  • 大白话: IOC 就是把创建对象和管理对象之间依赖关系的权力,从你自己手里转移到了 Spring 容器手里。 你不用自己 new 对象,也不用自己管对象之间的关系了,Spring 帮你搞定👍。

二、什么是 DI (依赖注入)?

  • 依赖: 房子需要砖头、水泥、钢筋,这些就是房子的"依赖"。

  • 注入: 建筑公司把砖头、水泥、钢筋"注入"到房子里,让房子可以盖起来🧱 🔨。

  • 大白话: DI 就是 Spring 容器把你的对象需要的"依赖"(比如其他的对象、配置信息等)自动"注入"到你的对象里。 你不用自己去 new 这些依赖,Spring 会自动帮你把它们放到正确的位置🚀。

三、为什么要有 IOC 和 DI?

  • 解耦: 想象一下,如果房子必须用特定品牌的砖头,那你就被这个品牌的砖头绑死了。 IOC 和 DI 可以让你更容易更换砖头(依赖),而不用修改房子的结构(代码)。
  • 可测试性: 如果房子里的水管是你自己焊的,那你想测试水管质量就很麻烦😫。 IOC 和 DI 可以让你更容易用模拟的水管(Mock 对象)来测试房子,而不用真的把水管焊上去✅。
  • 可维护性: 如果房子结构复杂,你自己管理所有的材料和工人,很容易出错🤯。 IOC 和 DI 可以让 Spring 帮你管理,减少你的负担,让代码更清晰易懂✨。
  • 简化开发: 你不用自己写大量的代码来创建对象和管理依赖关系,Spring 帮你做了很多,你可以更专注于业务逻辑🧘。

注意: IOC是一种设计思想,而DI是实现IOC的一种方式而已

四、IOC 和 DI 的好处

  • 降低耦合度: 各个组件之间的依赖关系由容器管理,组件之间不需要知道彼此的存在,降低了耦合度⬇️🔗。
  • 提高可测试性: 可以方便地使用 Mock 对象进行单元测试✅。
  • 提高可维护性: 代码结构更清晰,易于理解和维护🛠️。
  • 提高代码复用性: 组件可以被多个应用程序复用♻️。
  • 提高开发效率: 减少了手动管理对象依赖关系的工作量⚡。

五、应用实例

1. 简单示例:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component // 告诉 Spring Boot 这是一个组件,需要被管理
public class UserService {

    @Autowired // 告诉 Spring Boot,我需要一个 UserDao 对象
    private UserDao userDao;

    public String getUserName(int userId) {
        return userDao.getUserNameById(userId);
    }
}

@Component
public class UserDao {
    public String getUserNameById(int userId) {
        // 模拟从数据库获取用户名
        return "User-" + userId;
    }
}
  • 解释:
    • @Component: 告诉 Spring ,UserServiceUserDao 是组件,需要被 Spring 管理。
    • @Autowired: 告诉 Spring ,UserService 需要一个 UserDao 对象。 Spring 会自动创建一个 UserDao 对象,并把它"注入"到 UserService 中。
    • 你不需要自己 new UserDao(),Spring 帮你做了。

2. 使用配置文件注入:

java 复制代码
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class AppConfig {

    @Value("${app.name}") // 从 application.properties 中读取 app.name 的值
    private String appName;

    public String getAppName() {
        return appName;
    }
}
  • application.properties:
properties 复制代码
app.name=My Awesome App
  • 解释:
    • @Value: 告诉 Spring,从 application.properties 文件中读取 app.name 的值,并把它"注入"到 appName 变量中。
    • 你不需要自己读取配置文件,Spring 帮你做了。

3. 使用构造器注入:

java 复制代码
import org.springframework.stereotype.Component;

@Component
public class ReportService {

    private final DataProvider dataProvider;

    // 构造器注入
    public ReportService(DataProvider dataProvider) {
        this.dataProvider = dataProvider;
    }

    public String generateReport() {
        return "Report: " + dataProvider.getData();
    }
}

@Component
class DataProvider {
    public String getData() {
        return "Some Data";
    }
}
  • 解释:
    • ReportService 通过构造函数接收 DataProvider 的实例。
    • Spring 会自动找到 DataProvider 的 Bean,并将其注入到 ReportService 的构造函数中。
    • 构造器注入是推荐的方式,因为它能保证依赖的不可变性,并且更容易进行单元测试。

4. 使用接口和多态:

java 复制代码
public interface MessageService {
    String getMessage();
}

@Component("emailService")
public class EmailService implements MessageService {
    @Override
    public String getMessage() {
        return "Sending email...";
    }
}

@Component("smsService")
public class SMSService implements MessageService {
    @Override
    public String getMessage() {
        return "Sending SMS...";
    }
}

@Component
public class NotificationService {

    @Autowired
    @Qualifier("emailService") // 指定要注入哪个 MessageService
    private MessageService messageService;

    public void sendNotification() {
        System.out.println(messageService.getMessage());
    }
}
  • 解释:
    • MessageService 是一个接口,EmailServiceSMSService 是它的实现类。
    • @Qualifier: 告诉 Spring,要注入哪个 MessageService 的实现类。
    • 这种方式可以让你更容易切换不同的消息服务,而不用修改 NotificationService 的代码。

5. 更复杂的场景:

  • AOP (面向切面编程): 使用 IOC 和 DI 来管理切面,实现日志记录、权限控制等功能。
  • 事务管理: 使用 IOC 和 DI 来管理事务,保证数据的一致性。
  • 集成其他框架: 使用 IOC 和 DI 来集成 MyBatis、Hibernate 等框架。

六、总结

  • IOC: 就像你把盖房子的事情交给建筑公司,你不用自己管材料和工人了,Spring帮你管🏢。
  • DI: 就像建筑公司把砖头、水泥自动送到房子里,你不用自己去搬了,Spring帮你送🚚。
  • 好处: 代码更清晰、更容易修改、更容易测试,你更省心!😊

希望这篇文章能够帮助你理解 Spring中的 IOC 和 DI。 记住,多写代码,多实践,才能真正掌握它们!

相关推荐
cg50178 小时前
Spring Boot 的配置文件
java·linux·spring boot
橘猫云计算机设计11 小时前
基于springboot的考研成绩查询系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·考研·django·毕业设计
有一只柴犬12 小时前
深入Spring AI:6大核心概念带你入门AI开发
spring boot·后端
向阳25612 小时前
SpringBoot+vue前后端分离整合sa-token(无cookie登录态 & 详细的登录流程)
java·vue.js·spring boot·后端·sa-token·springboot·登录流程
XiaoLeisj12 小时前
【MyBatis】深入解析 MyBatis XML 开发:增删改查操作和方法命名规范、@Param 重命名参数、XML 返回自增主键方法
xml·java·数据库·spring boot·sql·intellij-idea·mybatis
风象南12 小时前
SpringBoot实现数据库读写分离的3种方案
java·spring boot·后端
CryptoPP13 小时前
springboot 对接马来西亚数据源API等多个国家的数据源
spring boot·后端·python·金融·区块链
清风絮柳13 小时前
52.个人健康管理系统小程序(基于springboot&vue)
vue.js·spring boot·毕业设计·前后端分离·健康管理系统·个人健康管理系统·个人健康管理小程序
forestsea13 小时前
使用 Spring Boot 和 GraalVM 的原生镜像
java·spring boot·spring native·原生映像
爱的叹息14 小时前
Spring Boot 集成Redis 的Lua脚本详解
spring boot·redis·lua