IoC容器深度解析:从手动new到自动装配的演进

引子:一个UserService的五种创建方式 假设你要创建一个UserService,它依赖UserRepository,而UserRepository又依赖DataSource。 这个看似简单的三层依赖,在不同的阶段有完全不同的创建方式: // 方式1:手动new(最原始) UserService userService = new UserService( new UserRepository( new DataSource("jdbc:mysql://localhost:3306/db", "root", "123456") ) ); // 方式2:工厂模式(稍好一点) UserService userService = UserServiceFactory.create(); // 方式3:依赖注入(手动装配) UserService userService = new UserService(); userService.setUserRepository(new UserRepository()); // 方式4:IoC容器(自动装配) ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = context.getBean(UserService.class); // 方式5:Spring Boot(零配置) @Autowired private UserService userService; // 自动注入 从方式1到方式5,到底发生了什么? 今天我们将通过5个渐进式场景,深度剖析IoC容器的演进逻辑,并亲手实现一个200行的简化版IoC容器。 一、场景0:手动new的噩梦(无容器) 1.1 三层依赖的手动创建 /** * 场景0:完全手动管理依赖 * 问题:硬编码、强耦合、难以测试 */ public class ManualDependencyDemo { public static void main(String[] args) { // 第1层:创建DataSource DataSource dataSource = new DataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/mydb"); dataSource.setUsername("root"); dataSource.setPassword("123456"); dataSource.setMaxPoolSize(10); // 第2层:创建UserRepository(依赖DataSource) UserRepository userRepository = new UserRepository(); userRepository.setDataSource(dataSource); // 第3层:创建UserService(依赖UserRepository) UserService userService = new UserService(); userService.setUserRepository(userRepository); // 使用 User user = userService.getUser(1L); System.out.println(user); } } /** * DataSource - 数据源 */ class DataSource { private String url; private String username; private String password; private int maxPoolSize; // getter/setter省略 } /** * UserRepository - 数据访问层 */ class UserRepository { private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public User findById(Long id) { // 使用dataSource查询数据库 System.out.println("查询数据库,dataSource: " + dataSource); return new User(id, "张三"); } } /** * UserService - 业务逻辑层 */ class UserService { private UserRepository userRepository; public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } public User getUser(Long id) { return userRepository.findById(id); } } /** * User - 实体类 */ class User { private Long id; private String name; public User(Long id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "User{id=" + id + ", name='" + name + "'}"; } } 1.2 核心问题分析 问题清单: ...

2025-11-03 · maneng

Spring源码深度解析:从使用者到贡献者

系列导航:本文是《Spring框架第一性原理》系列的第6篇(最终篇) 第1篇:为什么我们需要Spring框架? 第2篇:IoC容器:从手动new到自动装配的演进 第3篇:AOP:从代码重复到面向切面编程 第4篇:Spring Boot:约定优于配置的威力 第5篇:Spring Cloud:从单体到微服务的架构演进 第6篇:Spring源码深度解析(本文) 引子:为什么要阅读Spring源码? 三个真实场景 场景1:面试被问倒 面试官:"请说说Spring容器的启动流程?" 候选人:"Spring容器启动时会扫描注解,创建Bean,然后注入依赖..." 面试官:"具体一点,refresh()方法做了哪些事情?" 候选人:"呃...不太清楚..." 面试官:"那@Transactional是如何实现的?" 候选人:"通过AOP代理..." 面试官:"什么时候创建代理?代理怎么拦截方法?" 候选人:"这个...没深入研究过..." 结果:错失Offer 场景2:生产问题无从下手 线上问题:Spring容器启动失败 异常信息: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderService': Unsatisfied dependency expressed through field 'userService' 问题: ├─ orderService依赖userService ├─ 但容器中没有userService的Bean ├─ 为什么没有创建? └─ 如何定位问题? 不懂源码: ❌ 只能Google搜索错误信息 ❌ 盲目尝试各种配置 ❌ 浪费大量时间 懂源码: ✅ 知道Bean的创建流程 ✅ 知道依赖注入的机制 ✅ 快速定位到扫描路径配置错误 场景3:性能优化无从优化 问题:Spring应用启动慢(需要30秒) 不懂源码: ├─ 不知道启动时间花在哪里 ├─ 盲目减少Bean数量 └─ 效果有限 懂源码: ├─ 知道refresh()方法的12个步骤 ├─ 知道Bean创建的生命周期 ├─ 定位到瓶颈:@ComponentScan扫描了大量不必要的类 ├─ 优化扫描范围 └─ 启动时间降到5秒 阅读源码的五大收益 1. 面试加分 └─ 深入理解Spring原理,回答问题有理有据 └─ 知其然也知其所以然 2. 问题定位 └─ 遇到问题时,能快速定位根因 └─ 不再盲目Google,节省时间 3. 性能优化 └─ 知道性能瓶颈在哪里 └─ 有针对性地优化 4. 技术提升 └─ 学习优秀的代码设计 └─ 学习设计模式的实战应用 5. 贡献开源 └─ 有能力向Spring提交PR └─ 提升技术影响力 源码阅读准备 开发环境搭建 1. 下载Spring源码 # 1. 克隆Spring Framework仓库 git clone https://github.com/spring-projects/spring-framework.git # 2. 切换到稳定版本(推荐5.3.x) cd spring-framework git checkout v5.3.25 # 3. 查看项目结构 tree -L 1 . ├── spring-aop # AOP模块 ├── spring-aspects # AspectJ集成 ├── spring-beans # Bean管理核心 ├── spring-context # 应用上下文 ├── spring-core # 核心工具类 ├── spring-expression # SpEL表达式 ├── spring-jdbc # JDBC支持 ├── spring-orm # ORM集成 ├── spring-tx # 事务管理 ├── spring-web # Web基础 ├── spring-webmvc # Spring MVC └── spring-webflux # 响应式Web 2. 导入IDEA 步骤: 1. 打开IDEA → Open → 选择spring-framework目录 2. 等待Gradle构建完成(首次需要10-30分钟) 3. 构建完成后,项目结构如下: spring-framework/ ├── spring-beans/ │ └── src/main/java/ │ └── org/springframework/beans/ │ ├── factory/ │ │ ├── BeanFactory.java # Bean工厂接口 │ │ ├── support/ │ │ │ ├── AbstractBeanFactory.java │ │ │ └── DefaultListableBeanFactory.java │ │ └── config/ │ │ └── BeanDefinition.java # Bean定义 │ └── BeanWrapper.java ├── spring-context/ │ └── src/main/java/ │ └── org/springframework/context/ │ ├── ApplicationContext.java # 应用上下文接口 │ ├── support/ │ │ └── AbstractApplicationContext.java # 启动核心 │ └── annotation/ │ └── AnnotationConfigApplicationContext.java └── spring-aop/ └── src/main/java/ └── org/springframework/aop/ └── framework/ ├── ProxyFactory.java └── autoproxy/ └── AbstractAutoProxyCreator.java 常用快捷键: ├─ Ctrl+N (Mac: Cmd+O):搜索类 ├─ Ctrl+Shift+N:搜索文件 ├─ Ctrl+Alt+B (Mac: Cmd+Alt+B):查看接口实现 ├─ Ctrl+H:查看类层次结构 └─ Ctrl+F12:查看类的方法列表 3. 编写测试用例 // 创建测试项目:spring-source-test // pom.xml <dependencies> <!-- Spring核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.25</version> </dependency> <!-- 测试依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies> // 测试代码 @Configuration @ComponentScan("com.example") public class AppConfig { } @Component public class UserService { public void sayHello() { System.out.println("Hello from UserService"); } } // 测试类 public class SpringSourceTest { public static void main(String[] args) { // 在这里打断点,开始调试 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = context.getBean(UserService.class); userService.sayHello(); } } 调试技巧: 1. 在new AnnotationConfigApplicationContext(AppConfig.class)打断点 2. Step Into (F7),进入构造方法 3. 一步步跟踪执行流程 4. 关注关键方法:refresh()、invokeBeanFactoryPostProcessors()、finishBeanFactoryInitialization() 源码阅读方法论 方法1:从顶层接口入手 阅读顺序(IoC容器): 1. BeanFactory # 最顶层接口,定义基本功能 ├─ getBean() # 获取Bean ├─ containsBean() # 是否包含Bean └─ isSingleton() # 是否单例 2. ApplicationContext # 扩展接口,增强功能 ├─ 继承BeanFactory # Bean管理 ├─ 继承MessageSource # 国际化 ├─ 继承ApplicationEventPublisher # 事件发布 └─ 继承ResourceLoader # 资源加载 3. AbstractApplicationContext # 抽象实现类,定义模板 └─ refresh() # 核心方法,定义启动流程 4. AnnotationConfigApplicationContext # 具体实现类 └─ 使用注解配置 原则: ✅ 先看接口,理解设计意图 ✅ 再看抽象类,理解模板流程 ✅ 最后看具体实现,理解细节 ❌ 避免:直接看具体实现(容易迷失) 方法2:以功能为主线 功能主线1:Bean的创建流程 └─ 入口:ApplicationContext.getBean() └─ AbstractBeanFactory.doGetBean() └─ AbstractAutowireCapableBeanFactory.createBean() └─ AbstractAutowireCapableBeanFactory.doCreateBean() ├─ createBeanInstance() # 实例化 ├─ populateBean() # 属性填充 └─ initializeBean() # 初始化 功能主线2:AOP代理的创建 └─ 入口:@EnableAspectJAutoProxy └─ AspectJAutoProxyRegistrar └─ AnnotationAwareAspectJAutoProxyCreator └─ postProcessAfterInitialization() # Bean后置处理 └─ wrapIfNecessary() # 创建代理 功能主线3:事务的拦截 └─ 入口:@EnableTransactionManagement └─ TransactionInterceptor └─ invoke() # 拦截方法 ├─ createTransactionIfNecessary() # 开启事务 ├─ invokation.proceed() # 执行方法 └─ commitTransactionAfterReturning() # 提交事务 原则: ✅ 选择一个功能点,深入研究 ✅ 画出调用链路图 ✅ 理解每个方法的职责 ❌ 避免:同时看多个功能(容易混乱) 方法3:Debug + 日志 // 开启Spring Debug日志 logging.level.org.springframework=DEBUG // 在关键位置打断点 public class SpringSourceTest { public static void main(String[] args) { // 断点1:容器创建 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 断点2:Bean获取 UserService userService = context.getBean(UserService.class); // 断点3:方法调用 userService.sayHello(); } } // 查看调用栈 断点1命中时,查看Call Stack: main() └─ AnnotationConfigApplicationContext.<init>() └─ AbstractApplicationContext.refresh() ├─ prepareRefresh() ├─ obtainFreshBeanFactory() ├─ prepareBeanFactory() ├─ postProcessBeanFactory() ├─ invokeBeanFactoryPostProcessors() ← 处理@Configuration、@Bean ├─ registerBeanPostProcessors() ← 注册BeanPostProcessor ├─ initMessageSource() ├─ initApplicationEventMulticaster() ├─ onRefresh() ├─ registerListeners() └─ finishBeanFactoryInitialization() ← 创建所有单例Bean // 使用条件断点 右键断点 → Condition: beanName.equals("userService") # 只在创建userService时暂停 // 使用日志断点 右键断点 → Evaluate and log: "Creating bean: " + beanName # 记录日志,不暂停程序 IoC容器启动流程:refresh()方法深度剖析 refresh()方法概览 // AbstractApplicationContext.refresh() // 这是Spring容器启动的核心方法,包含12个步骤 @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准备刷新上下文环境 prepareRefresh(); // 2. 获取BeanFactory(告诉子类刷新内部BeanFactory) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 3. 准备BeanFactory(配置BeanFactory的标准上下文) prepareBeanFactory(beanFactory); try { // 4. BeanFactory后置处理(允许子类对BeanFactory进行后置处理) postProcessBeanFactory(beanFactory); // 5. 调用BeanFactory后置处理器(执行所有BeanFactoryPostProcessor) invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册Bean后置处理器(注册所有BeanPostProcessor) registerBeanPostProcessors(beanFactory); // 7. 初始化消息源(国际化) initMessageSource(); // 8. 初始化事件广播器 initApplicationEventMulticaster(); // 9. 刷新上下文(允许子类初始化特殊Bean,如内嵌Web容器) onRefresh(); // 10. 注册监听器 registerListeners(); // 11. 初始化所有单例Bean(非懒加载) finishBeanFactoryInitialization(beanFactory); // 12. 完成刷新(发布ContextRefreshedEvent事件) finishRefresh(); } catch (BeansException ex) { // 销毁已创建的Bean destroyBeans(); // 取消刷新 cancelRefresh(ex); throw ex; } finally { // 清理缓存 resetCommonCaches(); } } } 步骤1:prepareRefresh() - 准备刷新 protected void prepareRefresh() { // 1. 记录启动时间 this.startupDate = System.currentTimeMillis(); // 2. 设置容器状态 this.closed.set(false); // 未关闭 this.active.set(true); // 已激活 // 3. 初始化属性源(可由子类覆盖) initPropertySources(); // 4. 验证必需的属性 // 例如:getEnvironment().setRequiredProperties("JAVA_HOME"); getEnvironment().validateRequiredProperties(); // 5. 创建早期事件集合(在事件广播器准备好之前收集事件) if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // 6. 创建早期事件集合 this.earlyApplicationEvents = new LinkedHashSet<>(); } 作用: ✅ 记录启动时间(用于统计启动耗时) ✅ 设置容器状态(标记为激活状态) ✅ 初始化和验证环境变量 ✅ 准备事件监听器 步骤2:obtainFreshBeanFactory() - 获取BeanFactory protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 刷新BeanFactory(由子类实现) refreshBeanFactory(); // 返回BeanFactory return getBeanFactory(); } // AbstractRefreshableApplicationContext(XML配置) @Override protected final void refreshBeanFactory() throws BeansException { // 如果已有BeanFactory,先销毁 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 创建新的BeanFactory(DefaultListableBeanFactory) DefaultListableBeanFactory beanFactory = createBeanFactory(); // 设置序列化ID beanFactory.setSerializationId(getId()); // 定制BeanFactory(是否允许Bean覆盖、是否允许循环依赖) customizeBeanFactory(beanFactory); // 加载Bean定义(从XML文件) loadBeanDefinitions(beanFactory); // 保存BeanFactory引用 this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source", ex); } } // GenericApplicationContext(注解配置) @Override protected final void refreshBeanFactory() throws IllegalStateException { // 标记为已刷新 if (!this.refreshed.compareAndSet(false, true)) { throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts"); } // 设置序列化ID this.beanFactory.setSerializationId(getId()); } 对比: XML配置(AbstractRefreshableApplicationContext): └─ 每次refresh都创建新的BeanFactory └─ 从XML文件加载Bean定义 注解配置(GenericApplicationContext): └─ BeanFactory在构造方法中创建(只创建一次) └─ Bean定义通过注解扫描加载(在步骤5) 步骤3:prepareBeanFactory() - 准备BeanFactory protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 1. 设置类加载器 beanFactory.setBeanClassLoader(getClassLoader()); // 2. 设置SpEL表达式解析器 beanFactory.setBeanExpressionResolver( new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()) ); // 3. 添加属性编辑器注册器(用于类型转换) beanFactory.addPropertyEditorRegistrar( new ResourceEditorRegistrar(this, getEnvironment()) ); // 4. 添加BeanPostProcessor:ApplicationContextAwareProcessor // 作用:处理Aware接口回调(ApplicationContextAware、EnvironmentAware等) beanFactory.addBeanPostProcessor( new ApplicationContextAwareProcessor(this) ); // 5. 忽略以下Aware接口的依赖注入(由ApplicationContextAwareProcessor处理) beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // 6. 注册可解析的依赖(自动装配时使用) beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // 7. 添加BeanPostProcessor:ApplicationListenerDetector // 作用:检测ApplicationListener类型的Bean并注册到事件广播器 beanFactory.addBeanPostProcessor( new ApplicationListenerDetector(this) ); // 8. 如果存在LoadTimeWeaver,添加编织支持 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 9. 注册默认的环境Bean if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } } 作用: ✅ 配置类加载器、表达式解析器 ✅ 添加BeanPostProcessor(处理Aware接口回调) ✅ 注册可解析的依赖(BeanFactory、ApplicationContext等) ✅ 注册环境Bean(Environment、System Properties等) 步骤5:invokeBeanFactoryPostProcessors() - 执行BeanFactory后置处理器 这是最复杂也是最重要的步骤之一,负责处理@Configuration、@Bean、@ComponentScan等注解 ...

2025-11-03 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...