实现一个简化版的 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;
}
}
✅ 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);
}
}
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 代理 |
添加 ProxyFactory 和 BeanPostProcessor 实现 AOP |
十四、建议
- 理解 Spring 启动流程:从
BeanFactory
到 ApplicationContext
的封装
- 掌握反射和注解处理:Java 反射、
Field.set()
、isAnnotationPresent()
- 熟悉类路径扫描机制:
ClassLoader.getResources()
、File.listFiles()
、Class.forName()
- 理解单例和原型的区别:Spring 中
singletonObjects
缓存的作用
- 深入研究 Spring Boot 源码:如
AbstractBeanFactory
, AbstractAutowireCapableBeanFactory