# My Simple Spring Framework **Repository Path**: adent_sun/my-simple-spring-framework ## Basic Information - **Project Name**: My Simple Spring Framework - **Description**: Spring核心代码,包括IOC实现(包扫描,bean定义,bean的生命周期实现,AOP实现。) - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2025-10-10 - **Last Updated**: 2025-10-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # My-Spring Framework 一个简化版的 Spring 框架实现,演示了 Spring 核心概念的内部工作原理。 ## 目录 - [项目概述](#项目概述) - [架构设计](#架构设计) - [核心组件](#核心组件) - [ApplicationContext(IoC容器)](#applicationcontextioc容器) - [BeanDefinition(Bean定义)](#beandefinitionbean定义) - [注解系统](#注解系统) - [Spring源码对比分析](#spring源码对比分析) - [执行流程](#执行流程) - [使用示例](#使用示例) - [扩展点](#扩展点) - [常见问题](#常见问题) ## 项目概述 本项目是基于对 Spring 框架源码的理解而实现的一个简化版本,重现了 Spring 核心功能如控制反转(IoC)、依赖注入(Autowired方式)、组件扫描等机制。通过此项目可以深入了解 Spring 框架的设计理念和实现方式。 ## 架构设计 本项目遵循了 Spring 的核心设计理念,主要包括以下几个层次: 1. **配置层**:通过 AppConfig 类配置需要扫描的包路径 2. **扫描层**:扫描指定包下的组件并解析为 BeanDefinition 3. **注册层**:将 BeanDefinition 注册到容器中 4. **生命周期管理层**:管理 Bean 的实例化、依赖注入、初始化等过程 5. **访问层**:提供 getBean 等方法供外部获取 Bean 实例 ## 核心组件 ### ApplicationContext(IoC容器) 作为整个框架的核心,ApplicationContext 类承担着 BeanFactory 的角色,负责整个 Bean 生命周期的管理。它的职责包括: - 组件扫描与注册 - Bean 实例化与依赖注入 - Bean 生命周期管理 在 Spring 源码中,ApplicationContext 是一个复杂的接口体系,包含了大量的功能扩展。而在此简化版本中,我们聚焦于最核心的功能实现。 #### 核心方法 - `scan(Class configClass)`:扫描并解析带有 @Component 注解的类 - `preInstantiateSingletons()`:预实例化单例 Bean - `getBean(String beanName)`:获取 Bean 实例 - `getSingleton(String beanName)`:从单例池中获取 Bean ### BeanDefinition(Bean定义) BeanDefinition 是 Spring 中的一个重要概念,用于存储 Bean 的元数据信息。在本项目中,它保存了如下信息: - `beanClass`:Bean 对应的类 - `scope`:作用域(默认为 singleton) - `isLazy`:是否懒加载 - `isInterface`:是否为接口 这与 Spring 源码中的 RootBeanDefinition、GenericBeanDefinition 等类作用类似,都是用来抽象和描述 Bean 的定义信息。 ### 注解系统 为了实现组件的自动扫描和装配,项目实现了几个核心注解: #### @ComponentScan 相当于 Spring 中的 `@ComponentScan`,用于指定需要扫描的包路径。在 Spring 中,除了基础的包扫描功能外,还支持 includeFilters、excludeFilters 等高级筛选功能。 #### @Component 相当于 Spring 中的 `@Component`,用于标识一个类为 Spring 组件。Spring 还提供了更具体的派生注解如 `@Service`、`@Repository`、`@Controller` 等。 #### @Scope 用于指定 Bean 的作用域,在本项目中只实现了 singleton(单例)模式,Spring 原生还支持 prototype(原型)、request、session 等多种作用域。 #### @Lazy 用于指定 Bean 是否延迟初始化。在 Spring 中,可以通过在 `@Configuration` 类或 `@Bean` 方法上使用该注解来控制 Bean 的加载时机。 #### @Autowired 用于字段注入,目前仅支持按名称自动装配。Spring 中的 `@Autowired` 功能更为强大,支持按类型装配、按名称装配(配合 @Qualifier)、构造器注入等多种方式。 ## Spring源码对比分析 | 功能 | 本项目实现 | Spring 源码 | |------|------------|-------------| | IoC容器 | ApplicationContext 简化实现 | ApplicationContext 复杂接口体系,包含 BeanFactory、Environment 等 | | Bean定义 | BeanDefinition 简化实现 | 包含 RootBeanDefinition、GenericBeanDefinition、AnnotatedBeanDefinition 等多个实现 | | 组件扫描 | 基于 @ComponentScan 和 @Component | 支持多种过滤规则,可自定义 includeFilters/excludeFilters | | 依赖注入 | 简单的字段注入 | 支持字段注入、setter注入、构造器注入等多种方式 | | 生命周期 | InitializingBean 接口 | 包含 Aware 系列接口、InitializingBean、DisposableBean、@PostConstruct、@PreDestroy 等完整生命周期 | 本项目在实现上做了大量简化,去除了很多复杂的功能,专注于展示核心原理。 ## 执行流程 ### 1. 启动阶段 1. 应用程序启动,创建 ApplicationContext 实例并传入配置类 AppConfig ```java ApplicationContext ioc = new ApplicationContext(AppConfig.class); ``` 2. 在 ApplicationContext 构造函数中调用 `scan()` 方法扫描包路径下的组件 3. 解析所有带 @Component 注解的类并生成对应的 BeanDefinition 4. 将 BeanDefinition 注册到 beanDefinitionMap 中 ### 2. Bean后置处理器注册阶段 1. 调用 `registryBeanPostProcessor()` 方法注册所有实现了 BeanPostProcessor 接口的 Bean 2. 通过 `BeanPostProcessor.class.isAssignableFrom(beanClass)` 判断类是否实现了 BeanPostProcessor 接口 3. 将符合条件的处理器实例添加到 beanPostProcessors 列表中 ### 3. Bean实例化阶段 1. 调用 `preInstantiateSingletons()` 方法预实例化单例 Bean ```java private void preInstantiateSingletons() throws Exception { beanDefinitionMap.forEach((beanName,beanDefinition)->{ // 单例且非懒加载非接口 if(beanDefinition.isSingleton() && !beanDefinition.isLazy() && !beanDefinition.isInterface()){ try { System.out.println("开始创建bean:" + beanName); getBean(beanName); } catch (Exception e) { throw new RuntimeException(e); } } }); } ``` 2. 遍历 beanDefinitionMap,对于满足条件(单例、非懒加载、非接口)的 Bean 进行实例化 3. 调用 `getBean()` 方法创建 Bean 实例 ### 4. Bean创建过程 当调用 `getBean(String beanName)` 方法创建 Bean 时,会经历以下步骤: 1. **检查单例池**:首先从单例池 singletonObjects 中查找是否已存在实例 ```java Object bean = getSingleton(beanName); if (ObjectUtil.isNotNull(bean)) return bean; ``` 2. **实例化**:通过反射调用类的无参构造函数创建实例 ```java BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); Class beanClass = beanDefinition.getBeanClass(); Object instance = beanClass.getDeclaredConstructor().newInstance(); ``` 3. **依赖注入**:遍历实例的所有字段,查找带有 @Autowired 注解的字段并注入相应的依赖 ```java Field[] fields = instance.getClass().getDeclaredFields(); Arrays.stream(fields).forEach(field -> { // 判断是否是Autowired if(field.isAnnotationPresent(Autowired.class)){ // byName String fieldName = field.getName(); try { Object fieldBean = getBean(fieldName); field.setAccessible(true); // 设置属性值 field.set(finalInstance,fieldBean); } catch (Exception e) { throw new RuntimeException(e); } } }); ``` 4. **初始化前处理**:调用所有 BeanPostProcessor 的 `postProcessBeforeInitialization` 方法 ```java for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName); } ``` 5. **初始化**:如果 Bean 实现了 InitializingBean 接口,则调用 `afterPropertiesSet()` 方法 ```java if (instance instanceof InitializingBean) { // 回调 ((InitializingBean) instance).afterPropertiesSet(); } ``` 6. **初始化后处理**:调用所有 BeanPostProcessor 的 `postProcessAfterInitialization` 方法 ```java for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName); } ``` 7. **注册**:将创建完成的 Bean 实例放入单例池 singletonObjects 中 ```java singletonObjects.put(beanName,instance); ``` ### 5. Bean获取阶段 当调用 `getBean(String beanName)` 方法时: 1. 首先从单例池 singletonObjects 中查找是否存在已创建的实例 2. 如果存在则直接返回 3. 如果不存在则执行完整的创建流程 ## 使用示例 启动类:MyApplication.java ```java // 应用启动类 public class MyApplication { public static void main(String[] args) throws Exception { // 创建 ApplicationContext 容器 ApplicationContext ioc = new ApplicationContext(AppConfig.class); // 获取 Bean 实例 (注意:如果使用了AOP,应使用接口类型而非实现类) UserService userService = (UserService) ioc.getBean("userServiceImpl"); // 调用方法 userService.say(); } } ``` ## 扩展点 本项目虽然是简化版,但仍具备一定的扩展性: 1. **添加新的作用域**:可以在 BeanDefinition 中扩展更多作用域支持 2. **增强依赖注入**:可以扩展 @Autowired 注解的功能,支持按类型注入、构造器注入等 3. **添加更多生命周期接口**:可以实现类似 DisposableBean 等其他生命周期接口 4. **增加后置处理器**:可以实现类似 BeanPostProcessor 的机制处理 Bean 的初始化前后逻辑 通过这些扩展,可以让这个简化版的 Spring 更加完善,更接近真实的 Spring 框架。 ## 常见问题 ### 1. ClassCastException 类型转换异常 在使用 AOP 功能时,可能会遇到类似以下的错误: ``` Exception in thread "main" java.lang.ClassCastException: class jdk.proxy2.$Proxy4 cannot be cast to class com.zqh.app.service.impl.UserServiceImpl ``` **原因**:当使用 JDK 动态代理时,代理对象实现了目标类的接口,但它不是目标类的具体实现类型。 **解决方案**:应该使用接口类型而不是实现类进行类型转换。例如: ```java // 错误的方式 UserService userService = (UserServiceImpl) ioc.getBean("userServiceImpl"); // 正确的方式 UserService userService = (UserService) ioc.getBean("userServiceImpl"); ``` ### 2. BeanPostProcessor 未被正确识别 如果实现了 BeanPostProcessor 接口的类没有被正确识别和注册,需要确保: 1. 该类使用了 @Component 注解 2. 所在包被 @ComponentScan 扫描路径覆盖