Spring 源码解读:实现依赖注入的构造函数与Setter注入

引言

依赖注入(Dependency Injection)是Spring框架的核心特性之一,它通过将对象的依赖交由IoC容器管理,帮助开发者实现松耦合的代码结构。Spring支持多种依赖注入方式,其中最常见的是构造函数注入和Setter方法注入。本篇文章将通过一个完整的自定义IoC容器案例详细演示这两种注入方式,并进行深入的Spring 5.x源码解读。

第一部分:构造函数注入

1.1 构造函数注入的基本概念

构造函数注入是一种在对象创建时,通过构造函数将依赖传递给对象的方式。这种方式在对象创建时即保证了依赖的不可变性,适用于强制性依赖的场景。

1.2 自定义实现构造函数注入

我们将设计一个简单的IoC容器,支持通过构造函数注入依赖。

代码实现

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

// 定义Service接口,供Controller类依赖
interface Service {
   
   
    void execute();
}

// Service接口的具体实现类
class ServiceImpl implements Service {
   
   
    @Override
    public void execute() {
   
   
        System.out.println("Service is executing...");
    }
}

// Controller类依赖于Service接口
class Controller {
   
   
    private final Service service;

    // 通过构造函数注入Service实例
    public Controller(Service service) {
   
   
        this.service = service;
    }

    // 调用Service的方法
    public void doSomething() {
   
   
        service.execute();
    }
}

// 自定义的简单IoC容器,用于管理对象创建和依赖注入
public class SimpleIoCContainer {
   
   
    // 使用Map来存储Bean实例,key为类类型,value为对应的实例
    private Map<Class<?>, Object> beanMap = new HashMap<>();

    // 注册Bean,处理构造函数注入
    public void registerBean(Class<?> beanClass) {
   
   
        try {
   
   
            // 获取类的构造函数(假设每个类只有一个构造函数)
            Constructor<?> constructor = beanClass.getConstructors()[0];
            // 获取构造函数的参数类型
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            Object[] parameters = new Object[parameterTypes.length];

            // 递归处理依赖的实例化
            for (int i = 0; i < parameterTypes.length; i++) {
   
   
                parameters[i] = getBean(parameterTypes[i]);
            }

            // 使用构造函数创建对象实例
            Object bean = constructor.newInstance(parameters);
            // 将创建的实例注册到容器中
            beanMap.put(beanClass, bean);
        } catch (Exception e) {
   
   
            throw new RuntimeException("Failed to register bean: " + beanClass.getName(), e);
        }
    }

    // 获取Bean实例
    public <T> T getBean(Class<T> beanClass) {
   
   
        // 如果容器中还没有这个类型的实例,就先注册一个
        if (!beanMap.containsKey(beanClass)) {
   
   
            registerBean(beanClass);
        }
        // 返回已注册的实例
        return beanClass.cast(beanMap.get(beanClass));
    }

    public static void main(String[] args) {
   
   
        // 创建IoC容器
        SimpleIoCContainer container = new SimpleIoCContainer();

        // 获取Controller实例,依赖自动注入
        Controller controller = container.getBean(Controller.class);

        // 使用Controller
        controller.doSomething();
    }
}

详细解释:

  • SimpleIoCContainer通过反射机制处理构造函数注入。registerBean()方法负责根据构造函数参数类型递归创建对象并注册到容器中。
  • getBean()方法用于获取已注册的Bean实例。如果Bean未注册,容器会自动注册并创建该Bean。
  • main()方法展示了如何使用这个IoC容器来管理Controller和它的依赖Service
1.3 构造函数注入的类图和流程图
类图
SimpleIoCContainer
-Map<Class, Object> beanMap
+void registerBean(Class beanClass)
+T getBean(Class<T> beanClass)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

捕风捉你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值