手写一个简化版的Spring Ioc容器(一)

实现一个简化版的 IoC 容器,模拟 Spring 的核心机制:组件扫描、Bean 管理、依赖注入、单例模式、注解驱动(@Component, @Autowired, @Qualifier)和 BeanFactory / ApplicationContext 的基本结构。


一、实现目标

功能 是否支持
@Component 注解
@Autowired 注解
@Qualifier 注解
单例作用域
原型作用域 ❌(可扩展)
构造函数注入 ❌(可扩展)
BeanFactory / ApplicationContext 抽象
BeanDefinition 元信息管理
类路径扫描(ClassPathBeanDefinitionScanner
BeanPostProcessor
InitializingBean / init-method
DisposableBean / destroy-method

二、项目结构

simple-ioc/
├── annotation/
│   ├── Component.java
│   ├── Autowired.java
│   └── Qualifier.java
├── bean/
│   ├── BeanDefinition.java
│   ├── DefaultListableBeanFactory.java
│   ├── SimpleBeanFactory.java
│   └── SimpleApplicationContext.java
├── service/
│   ├── UserService.java
│   └── UserRepository.java
└── Main.java

三、核心类与接口

✅ 1. Component 注解(模仿 Spring @Component

package simple.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value() default "";
}

✅ 2. Autowired 注解(模仿 Spring @Autowired

package simple.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface Autowired {}

✅ 3. Qualifier 注解(模仿 Spring @Qualifier

package simple.ioc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface Qualifier {
    String value();
}

四、核心容器类

✅ 1. BeanDefinition(Bean 的元信息)

package simple.ioc.bean;

public class BeanDefinition {
    private String beanName;
    private Class<?> beanClass;
    private Object bean;
    private boolean isSingleton;
    private boolean isPrototype;
    private String initMethod;
    private String destroyMethod;

    public BeanDefinition(String beanName, Class<?> beanClass) {
        this.beanName = beanName;
        this.beanClass = beanClass;
        this.isSingleton = true; // 默认单例
    }

    // Getters & Setters
}

✅ 2. BeanFactory 接口(IoC 容器接口)

package simple.ioc.bean;

public interface BeanFactory {
    Object getBean(String name) throws Exception;
    void registerBeanDefinition(String name, BeanDefinition bd);
    boolean containsBean(String name);
}

✅ 3. SimpleBeanFactory(IoC 容器实现)

package simple.ioc.bean;

import java.util.HashMap;
import java.util.Map;

public class SimpleBeanFactory implements BeanFactory {
    private final Map<String, BeanDefinition> beanDefinitions = new HashMap<>();
    private final Map<String, Object> singletonObjects = new HashMap<>();

    @Override
    public Object getBean(String name) throws Exception {
        if (!containsBean(name)) {
            throw new RuntimeException("Bean [" + name + "] not found");
        }

        BeanDefinition bd = beanDefinitions.get(name);
        if (bd.isSingleton()) {
            if (!singletonObjects.containsKey(name)) {
                singletonObjects.put(name, createBean(bd));
            }
            return singletonObjects.get(name);
        } else {
            return createBean(bd);
        }
    }

    private Object createBean(BeanDefinition bd) throws Exception {
        Object bean = bd.getBeanClass().getDeclaredConstructor().newInstance();

        // 自动注入依赖
        for (Field field : bean.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);

                Qualifier qualifier = field.getAnnotation(Qualifier.class);
                String dependencyName = qualifier != null ? qualifier.value() : field.getType().getName();
                Object dependency = getBean(dependencyName);
                field.set(bean, dependency);
            }
        }

        // 初始化 Bean
        if (bean instanceof InitializingBean) {
            ((InitializingBean) bean).afterPropertiesSet();
        }

        return bean;
    }

    @Override
    public void registerBeanDefinition(String name, BeanDefinition bd) {
        beanDefinitions.put(name, bd);
    }

    @Override
    public boolean containsBean(String name) {
        return beanDefinitions.containsKey(name);
    }

    public void destroySingletons() {
        for (Object bean : singletonObjects.values()) {
            if (bean instanceof DisposableBean) {
                try {
                    ((DisposableBean) bean).destroy();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        singletonObjects.clear();
    }
}

✅ 4. DefaultListableBeanFactory(继承 SimpleBeanFactory,支持组件扫描)

package simple.ioc.bean;

import simple.ioc.annotation.Component;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class DefaultListableBeanFactory extends SimpleBeanFactory {

    public void scan(String basePackage) throws Exception {
        List<Class<?>> classes = findClasses(basePackage);
        for (Class<?> clazz : classes) {
            if (clazz.isAnnotationPresent(Component.class)) {
                Component component = clazz.getAnnotation(Component.class);
                String beanName = component.value().isEmpty() ? clazz.getSimpleName() : component.value();
                registerBeanDefinition(beanName, new BeanDefinition(beanName, clazz));
            }
        }
    }

    private List<Class<?>> findClasses(String packageName) throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL packageResource = classLoader.getResource(packageName.replace('.', '/'));
        File packageFolder = new File(packageResource.getFile());

        List<Class<?>> classes = new ArrayList<>();
        for (File file : packageFolder.listFiles((dir, name) -> name.endsWith(".class"))) {
            String className = packageName + "." + file.getName().replace(".class", "");
            classes.add(classLoader.loadClass(className));
        }
        return classes;
    }
}

✅ 5. SimpleApplicationContext(IoC 容器上下文)

package simple.ioc.bean;

public class SimpleApplicationContext {
    private final DefaultListableBeanFactory beanFactory;

    public SimpleApplicationContext(String basePackage) throws Exception {
        beanFactory = new DefaultListableBeanFactory();
        beanFactory.scan(basePackage);
    }

    public Object getBean(String name) throws Exception {
        return beanFactory.getBean(name);
    }

    public void close() {
        beanFactory.destroySingletons();
    }
}

五、Bean 生命周期接口

✅ 1. InitializingBean(模仿 Spring InitializingBean

package simple.ioc.bean;

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

✅ 2. DisposableBean(模仿 Spring DisposableBean

package simple.ioc.bean;

public interface DisposableBean {
    void destroy() throws Exception;
}

六、示例代码

✅ 1. UserRepository(被依赖的 Bean)

package simple.ioc.service;

import simple.ioc.annotation.Component;

@Component
public class UserRepository {
    public void save() {
        System.out.println("User saved");
    }
}

✅ 2. UserService(依赖注入示例)

package simple.ioc.service;

import simple.ioc.annotation.Autowired;
import simple.ioc.annotation.Component;
import simple.ioc.annotation.Qualifier;
import simple.ioc.bean.InitializingBean;
import simple.ioc.bean.DisposableBean;

@Component("userService")
public class UserService implements InitializingBean, DisposableBean {

    @Autowired
    @Qualifier("UserRepository")
    private UserRepository userRepository;

    public void doSomething() {
        userRepository.save();
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("UserService initialized");
    }

    @Override
    public void destroy() {
        System.out.println("UserService destroyed");
    }
}

七、测试类 Main.java

import simple.ioc.bean.SimpleApplicationContext;

public class Main {
    public static void main(String[] args) throws Exception {
        SimpleApplicationContext context = new SimpleApplicationContext("simple.ioc.service");

        UserService userService = (UserService) context.getBean("userService");
        userService.doSomething();

        context.close();
    }
}

✅ 八、输出结果(运行 Main.java

UserService initialized
User saved
UserService destroyed

九、IoC 容器的工作流程图(简化版)

SimpleApplicationContext 初始化
 └── 扫描包路径
      └── 加载类文件
           └── 判断是否带有 @Component 注解
                └── 注册为 BeanDefinition
                     └── BeanFactory.registerBeanDefinition()

SimpleApplicationContext.getBean()
 └── 判断是否已存在单例 Bean
      └── 不存在则调用 createBean()
           └── newInstance() 创建 Bean 实例
           └── 遍历字段 → 找到 @Autowired 字段
                └── 调用 getBean() 注入依赖
           └── 调用 InitializingBean.afterPropertiesSet()
                └── 返回 Bean 实例

SimpleApplicationContext.close()
 └── 调用 DisposableBean.destroy()

十、可扩展点(可以继续添加)

功能 实现方式
构造器注入 createBean() 中处理构造器参数
原型作用域 BeanDefinition 中支持 prototype
XML 配置 添加 XmlBeanDefinitionReader 解析 XML
@Value 注解 添加字段解析逻辑,结合 Environment
BeanPostProcessor 添加前置/后置处理逻辑
@Scope 注解 支持 prototype、request、session 等作用域
@ComponentScan 模仿 Spring 的组件扫描机制
@Primary / @Qualifier 改进 多个同类型 Bean 的优先级和名称匹配
@Import / @Configuration 实现配置类导入机制

✅ 十一、总结

特性 实现说明
组件扫描 通过 DefaultListableBeanFactory.scan() 实现类路径扫描
Bean 管理 使用 SimpleBeanFactory 注册和管理 Bean
依赖注入 通过反射注入带有 @Autowired 的字段
生命周期管理 支持 InitializingBean, DisposableBean
注解驱动 使用 @Component, @Autowired, @Qualifier
单例模式 默认单例,通过 singletonObjects 缓存管理
销毁钩子 通过 DisposableBean.destroy() 实现关闭逻辑

十二、完整代码结构

代码组织为如下结构:

src/
├── simple/
│   └── ioc/
│       ├── annotation/
│       │   ├── Component.java
│       │   ├── Autowired.java
│       │   └── Qualifier.java
│       ├── bean/
│       │   ├── BeanDefinition.java
│       │   ├── BeanFactory.java
│       │   ├── SimpleBeanFactory.java
│       │   └── SimpleApplicationContext.java
│       │   ├── InitializingBean.java
│       │   └── DisposableBean.java
│       └── service/
│           ├── UserService.java
│           └── UserRepository.java
└── Main.java

十三、后续扩展建议

进一步扩展这个 IoC 容器,可以考虑以下功能:

功能 实现方式
构造器注入 createBean() 中解析构造方法并注入
原型作用域 BeanDefinition 中添加 prototype 支持
@Value 支持 添加 Environment 解析 ${} 占位符
@ComponentScan 使用自定义注解驱动扫描
@Primary / @Qualifier 改进 getBean() 的匹配逻辑
BeanPostProcessor 添加前置/后置处理器链
BeanFactoryPostProcessor 添加 BeanDefinition 修改机制
@Configuration / @Bean 添加配置类支持
@Import 添加自动配置类导入机制
AOP 代理 添加 ProxyFactoryBeanPostProcessor 实现 AOP

十四、建议

  • 理解 Spring 启动流程:从 BeanFactoryApplicationContext 的封装
  • 掌握反射和注解处理:Java 反射、Field.set()isAnnotationPresent()
  • 熟悉类路径扫描机制ClassLoader.getResources()File.listFiles()Class.forName()
  • 理解单例和原型的区别:Spring 中 singletonObjects 缓存的作用
  • 深入研究 Spring Boot 源码:如 AbstractBeanFactory, AbstractAutowireCapableBeanFactory

你可能感兴趣的:(spring,java,spring,java,后端)