本文目录导读:

我来教你实现一个简单的IoC容器,从基础到逐步完善,我会用Java语言演示,因为它的反射机制最清晰。
核心概念
IoC容器的三个核心功能:
- 注册:告诉容器哪些类需要管理
- 解析:分析类之间的依赖关系
- 注入:自动创建依赖实例
最简实现
先从一个基础版本开始:
import java.lang.reflect.Field;
import java.util.*;
// 注解:标记需要注入的字段
@interface Inject {
}
// 简单IoC容器
class SimpleContainer {
// 存储已注册的类和对应的实例
private Map<Class<?>, Object> instances = new HashMap<>();
// 注册接口与实现类
public <T> void register(Class<T> interfaceClass, T implementation) {
instances.put(interfaceClass, implementation);
}
// 获取bean实例(自动注入依赖)
@SuppressWarnings("unchecked")
public <T> T getBean(Class<T> clazz) throws Exception {
// 如果已有实例,直接返回
if (instances.containsKey(clazz)) {
return (T) instances.get(clazz);
}
// 创建新实例
T instance = clazz.getDeclaredConstructor().newInstance();
instances.put(clazz, instance);
// 注入依赖
injectDependencies(instance);
return instance;
}
// 注入依赖
private void injectDependencies(Object instance) throws Exception {
Class<?> clazz = instance.getClass();
// 遍历所有字段
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Inject.class)) {
field.setAccessible(true);
// 获取依赖的类型
Class<?> fieldType = field.getType();
// 递归获取依赖实例
Object dependency = getBean(fieldType);
field.set(instance, dependency);
}
}
}
}
使用示例
// 定义接口和类
interface Database {
void query(String sql);
}
class MySQLDatabase implements Database {
@Override
public void query(String sql) {
System.out.println("MySQL执行: " + sql);
}
}
class UserService {
@Inject // 标记需要注入
private Database database;
public void findUser(int id) {
database.query("SELECT * FROM users WHERE id = " + id);
}
}
// 使用容器
public class Main {
public static void main(String[] args) throws Exception {
SimpleContainer container = new SimpleContainer();
// 注册数据库实现
container.register(Database.class, new MySQLDatabase());
// 获取UserService(自动注入Database)
UserService userService = container.getBean(UserService.class);
userService.findUser(1);
}
}
增强版本
添加更多功能:
import java.lang.reflect.Constructor;
import java.util.*;
// 支持单例和原型模式
enum Scope {
SINGLETON, // 单例
PROTOTYPE // 原型(每次新建)
}
// 增强的容器
class AdvancedContainer {
// 存储单例实例
private Map<Class<?>, Object> singletons = new HashMap<>();
// 存储Bean定义
private Map<Class<?>, BeanDefinition> beanDefinitions = new HashMap<>();
// Bean定义
static class BeanDefinition {
Class<?> clazz;
Scope scope = Scope.SINGLETON;
BeanDefinition(Class<?> clazz) {
this.clazz = clazz;
}
}
// 注册类
public void register(Class<?> clazz) {
beanDefinitions.put(clazz, new BeanDefinition(clazz));
}
// 注册并指定作用域
public void register(Class<?> clazz, Scope scope) {
BeanDefinition def = new BeanDefinition(clazz);
def.scope = scope;
beanDefinitions.put(clazz, def);
}
// 获取Bean
@SuppressWarnings("unchecked")
public <T> T getBean(Class<T> clazz) throws Exception {
BeanDefinition def = beanDefinitions.get(clazz);
if (def == null) {
throw new IllegalArgumentException("Bean not registered: " + clazz);
}
// 单例模式
if (def.scope == Scope.SINGLETON) {
if (!singletons.containsKey(clazz)) {
singletons.put(clazz, createInstance(clazz));
}
return (T) singletons.get(clazz);
}
// 原型模式
return (T) createInstance(clazz);
}
// 创建实例并注入依赖
private Object createInstance(Class<?> clazz) throws Exception {
// 查找合适的构造器
Constructor<?> constructor = findConstructor(clazz);
Object instance;
if (constructor != null) {
// 通过构造器注入
Class<?>[] paramTypes = constructor.getParameterTypes();
Object[] params = new Object[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
params[i] = getBean(paramTypes[i]);
}
instance = constructor.newInstance(params);
} else {
// 使用默认构造器
instance = clazz.getDeclaredConstructor().newInstance();
}
// 字段注入
injectFields(instance);
return instance;
}
// 查找带@Inject注解的构造器
private Constructor<?> findConstructor(Class<?> clazz) {
for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
if (constructor.isAnnotationPresent(Inject.class)) {
return constructor;
}
}
return null;
}
// 字段注入
private void injectFields(Object instance) throws Exception {
Class<?> clazz = instance.getClass();
for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Inject.class)) {
field.setAccessible(true);
Object dependency = getBean(field.getType());
field.set(instance, dependency);
}
}
}
}
完整的实战示例
// 演示基于接口的编程
interface Logger {
void log(String message);
}
class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("[Console] " + message);
}
}
// 使用构造器注入
class OrderService {
private final Logger logger;
private final Database database;
@Inject // 标记构造器注入
public OrderService(Logger logger, Database database) {
this.logger = logger;
this.database = database;
}
public void createOrder(String orderId) {
logger.log("Creating order: " + orderId);
database.query("INSERT INTO orders VALUES ('" + orderId + "')");
logger.log("Order created successfully");
}
}
// 测试
public class Demo {
public static void main(String[] args) throws Exception {
AdvancedContainer container = new AdvancedContainer();
// 注册组件
container.register(ConsoleLogger.class);
container.register(MySQLDatabase.class);
container.register(OrderService.class);
// 创建服务(依赖自动注入)
OrderService orderService = container.getBean(OrderService.class);
orderService.createOrder("ORD-001");
}
}
关键设计要点
- 类型识别:使用
Class<?>作为键来标识和管理Bean - 依赖解析:通过反射分析构造器参数和字段
- 生命周期管理:区分单例和原型模式
- 循环依赖处理:可以通过三级缓存解决(Spring的方案)
这个实现虽然简单,但包含了IoC容器的核心思想,实际生产中可以借鉴Spring的实现思路,添加更多功能如AOP、配置文件支持等。