手把手实现一个简化版 Spring 框架

Scroll Down

🚀 手写一个 Mini-Spring 框架,从零打造你的 Spring 框架!

Spring 框架 是 Java 生态的核心,掌握其原理后,我们可以自己实现一个简化版的 Spring 框架!
本文将带你 手写一个 Mini-Spring 框架,从 IOC 容器、Bean 管理、AOP 切面、事务支持 等核心功能入手,助你成为 Spring 领域专家!


📌 1. 什么是 Mini-Spring?(What)

Mini-Spring 目标是 简化版 Spring 框架,具备以下核心能力:
IOC(控制反转):实现 Bean 容器,支持 @ComponentScan 自动扫描
DI(依赖注入):支持 @Autowired 注入 Bean
AOP(切面编程):基于动态代理实现 @Aspect
事务管理:基于 @Transactional 实现数据库事务控制


📌 2. 为什么要手写 Spring 框架?(Why)

✅ 深入理解 Spring 核心原理,提高技术竞争力
✅ 掌握 IOC、AOP、事务管理,增强源码分析能力
✅ 解决实际问题,提升 面试 & 项目经验


📌 3. 如何实现 Mini-Spring?(How)

我们分 4 步 实现一个 Mini-Spring 框架!

🛠️ 第 1 步:实现 IOC 容器

Spring 的核心是 IOC 容器,负责 Bean 的加载与管理。
我们使用 反射 + 注解 实现 Bean 容器。

🔍 代码实现:

public class MiniApplicationContext {
    private Map<String, Object> beanMap = new HashMap<>();

    public MiniApplicationContext(String basePackage) {
        scanAndLoadBeans(basePackage);
    }

    private void scanAndLoadBeans(String basePackage) {
        // 1. 扫描 @Component 标注的类
        List<Class<?>> classes = scanClasses(basePackage);
        for (Class<?> clazz : classes) {
            if (clazz.isAnnotationPresent(Component.class)) {
                try {
                    // 2. 实例化 Bean 并存入 Map
                    Object instance = clazz.newInstance();
                    beanMap.put(clazz.getSimpleName(), instance);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    private List<Class<?>> scanClasses(String basePackage) {
        List<Class<?>> classList = new ArrayList<>();
        String path = basePackage.replace(".", "/"); // 将包名转换为路径
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL resource = classLoader.getResource(path);

        if (resource == null) {
            throw new RuntimeException("未找到包路径: " + path);
        }

        File dir = new File(resource.getFile());
        if (dir.exists() && dir.isDirectory()) {
            for (File file : dir.listFiles()) {
                if (file.getName().endsWith(".class")) {
                    try {
                        String className = basePackage + "." + file.getName().replace(".class", "");
                        Class<?> clazz = Class.forName(className);
                        classList.add(clazz);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException("加载类失败: " + file.getName(), e);
                    }
                }
            }
        }
        return classList;
    }

    public Object getBean(String beanName) {
        return beanMap.get(beanName);
    }
}

📌 优化点

  • 使用 @Component 自动扫描 Bean
  • 支持 getBean() 获取实例

🛠️ 第 2 步:实现依赖注入(DI)

Spring 通过 @Autowired 自动注入,我们用 反射 实现依赖注入。

🔍 代码实现:

public void injectDependencies() {
    for (Object bean : beanMap.values()) {
        for (Field field : bean.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Autowired.class)) {
                try {
                    field.setAccessible(true);
                    field.set(bean, getBean(field.getType().getSimpleName()));
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

📌 优化点

  • 自动注入 @Autowired 依赖
  • 使用反射设置 setAccessible(true)

🛠️ 第 3 步:实现 AOP 切面

Spring AOP 允许我们 动态代理方法,实现 日志、事务、权限控制 等功能。
我们用 JDK 动态代理 实现 @Aspect

🔍 代码实现:

public class ProxyFactory {
    public static Object createProxy(Object target, InvocationHandler handler) {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            handler
        );
    }
}

📌 优化点

  • 动态代理拦截方法
  • 适用于 AOP 切面(如日志、事务)

🛠️ 第 4 步:实现事务管理

Spring @Transactional 通过 AOP 拦截数据库操作,我们用 代理模式 实现事务管理。

🔍 代码实现:

public class TransactionInterceptor implements InvocationHandler {
    private Object target;
    private DataSource dataSource;

    public TransactionInterceptor(Object target, DataSource dataSource) {
        this.target = target;
        this.dataSource = dataSource;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Connection conn = dataSource.getConnection();
        try {
            conn.setAutoCommit(false);  // 开启事务
            Object result = method.invoke(target, args);
            conn.commit();  // 提交事务
            return result;
        } catch (Exception e) {
            conn.rollback();  // 回滚事务
            throw e;
        }
    }
}

📌 优化点

  • 自动管理事务提交 & 回滚
  • 提高数据库操作的安全性

📌 4. 实战案例:用 Mini-Spring 启动应用

我们使用 Mini-Spring 创建一个 UserService 并自动注入。

🛠️ 代码示例

@Component
public class UserService {
    public void createUser() {
        System.out.println("创建用户成功!");
    }
}

public class MiniSpringApp {
    public static void main(String[] args) {
        MiniApplicationContext context = new MiniApplicationContext("com.example");
        UserService userService = (UserService) context.getBean("UserService");
        userService.createUser();
    }
}

最终效果:

  • 自动扫描 @Component 并注册 Bean
  • 实现 @Autowired 自动注入
  • 支持 AOP 事务管理

📌 5. 总结

🔥 我们成功手写了一个 Mini-Spring 框架,包含:
1️⃣ IOC 容器(自动扫描 & Bean 注册)
2️⃣ DI 依赖注入(支持 @Autowired 自动注入)
3️⃣ AOP 切面编程(支持动态代理)
4️⃣ 事务管理(基于 @Transactional 实现事务回滚)

🚀 掌握这些技术,你就能真正理解 Spring 框架的核心原理,并打造属于自己的框架!
💡 你有什么想法?欢迎留言交流! 🎯