java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring IoC容器与依赖倒置(DI)

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

作者:Yan.love

文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyBatis则通过动态代理实现了接口方法到数据库操作的映射,文章详细解释了Spring和MyBatis的工作原理,并通过示例代码展示了它们的结合使用方式

在日常开发中,我们总会面临一个问题:如何优雅地管理对象的创建和依赖? 你可能会写一堆代码来手动构造对象,但这种方式繁琐且难以维护。而当项目变得复杂,依赖链拉长,手动管理对象的方式很快就会捉襟见肘。

这时,Spring 的 IoC 和 DI 机制便是解放双手的利器,它让开发者专注于业务逻辑,容器则负责对象的创建与依赖管理。与此同时,MyBatis 的动态代理更是省去了为每个接口手动实现类的麻烦,极大地提高了效率。

但你有没有想过,Spring 是如何找到你的类并自动注入依赖的?MyBatis 又是如何在没有实现类的情况下完成数据库操作的?如果你也有这些疑问,那恭喜你,今天的内容正是为你准备的!

一、控制反转 IoC

控制反转(Inversion of Control, IoC) 是一种设计思想。它强调将控制权从对象本身转移到容器中。服务中心(容器)负责管理各种资源(对象和依赖)。用户(对象)需要资源时,服务中心将资源提供给它。容器控制对象的创建、依赖注入和生命周期管理

在传统编程中,对象需要自己控制依赖的创建和管理;在 IoC 中,这些任务由容器负责。

容器根据 Bean 的依赖关系,通过 DI 注入所需的依赖。

二、依赖倒置 DI

1. 详细概念

依赖注入(Dependency Injection, DI) 是 IoC 的具体实现方式之一。

它通过注入的方式,将对象需要的依赖提供给它,而不是由对象自己去创建,Spring会按需创建相应的对象,通过构造器、Setter 方法或字段注入,把依赖传递给对象。

2. Spring 中 DI 的实现原理

三、注册Bean过程:以 Spring+Mybatis 为例

1. Spring 是如何通过注解注册 Bean 的

Spring 通过 组件扫描(Component Scanning)注解识别 将类注册为 Bean。

注册过程

2. MyBatis是如何动态生成 UserMapper 的实现类的

UserMapper 是接口,没有具体实现类。MyBatis 会利用 @Mapper 注解,结合 Mapper 配置文件或注解中的 SQL 语句,动态生成代理实现类

代理类生成过程

动态代理机制:MyBatis 使用 JDK 动态代理,为每个 Mapper 接口生成一个代理类。

InvocationHandler:代理类拦截所有对接口方法的调用,将它们转发到 MyBatis 的核心组件(如 SqlSession)执行 SQL。

3. @Autowired 注入过程

注入逻辑

找到目标 Bean

依赖注入

// 获取字段
Field field = UserServiceImpl.class.getDeclaredField("userMapper");
// 使私有字段可访问
field.setAccessible(true);
// 将找到的 UserMapper Bean 注入到 userServiceImpl 实例
field.set(userServiceImplInstance, userMapperBean);

4. 总结:Spring 与 MyBatis 的结合

Spring

MyBatis

附加:代理类与 UserMapper 实现类的差异

代理类

普通实现类

示例对比

// 动态代理生成的代理类示例
public class UserMapperProxy implements UserMapper {
    private final SqlSession sqlSession;
​
    public UserMapperProxy(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }
​
    @Override
    public User findById(int id) {
        // 将方法调用转化为 MyBatis 的 SQL 执行
        return sqlSession.selectOne("namespace.findById", id);
    }
}
​
// 普通实现类(手动实现)
public class UserMapperImpl implements UserMapper {
    @Override
    public User findById(int id) {
        // 自己写逻辑,连接数据库,执行 SQL
        return executeSQL("SELECT * FROM user WHERE id = ?", id);
    }
}

动态代理的优势在于:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文