Spring核心原理小结

Spring核心原理小结 一、Spring是什么Spring 是一个管理 Java 对象的容器 工具框架帮助开发者省去手动创建对象、管理依赖、处理复杂逻辑的麻烦。核心目标简化开发解耦代码。二、Spring三大核心基石1. IOC控制反转—— 最核心原理本质Spring 读取配置 → 扫描类 → 创建对象 → 填充依赖 → 存入容器 → 供你使用的全过程通俗理解以前是你自己new 对象()现在交给Spring 容器来创建、管理、销毁对象。谁控制谁Spring 容器控制对象的生命周期反转了什么对象创建权从「开发者手动创建」反转成「Spring 自动创建」核心作用解耦不用在代码里硬编码对象降低耦合度。(1)IOC执行流程第 1 步容器启动加载配置你启动 Spring 容器如ClassPathXmlApplicationContext/AnnotationConfigApplicationContextSpring 开始加载配置XML、注解、JavaConfig 等目的知道要管理哪些类、哪些 Bean第 2 步扫描组件定位 BeanSpring 根据配置扫描包路径识别带有Component / Service / Controller / Repository等注解的类把这些类的全类名、作用域、依赖信息收集起来第 3 步封装 BeanDefinition核心数据结构Spring 不会直接创建对象先把每个要管理的类封装成 BeanDefinition 对象存放类路径、是否单例、是否懒加载、依赖属性…所有 BeanDefinition 存到一个Map里第 4 步BeanFactoryPostProcessor 处理扩展点Spring 允许在创建对象前修改 BeanDefinition比如修改属性、替换类路径、加载外部配置文件这是容器级别的扩展接口第 5 步实例化 Bean创建空对象Spring 通过反射调用构造方法创建 Bean 实例此时对象只是空壳属性还没赋值单例 Bean 会立即创建多例 Bean 用到时才创建第 6 步依赖注入DI 赋值Spring 自动扫描对象需要的依赖Autowired / Resource从容器中找到对应的 Bean通过 setter / 构造方法 / 字段注入对象从此拥有完整属性第 7 步执行 Aware 接口感知容器如果 Bean 实现了BeanNameAware、ApplicationContextAware等接口Spring 会把容器自身、Bean 名称等信息传给对象让 Bean 能感知 Spring 容器第 8 步初始化前后AOP 生成代理执行 BeanPostProcessor 前置处理执行初始化方法PostConstruct/init-method执行 BeanPostProcessor 后置处理✅这里就是 AOP 生成代理对象的地方第 9 步将 Bean 放入单例池单例 Bean 会被存入MapString, Object singletonObjects以后获取 Bean 直接从这里拿不用重新创建这就是 Spring 单例的实现原理第 10 步Bean 就绪供使用你可以通过getBean()或直接注入使用 Bean容器关闭时执行销毁方法PreDestroy(2) 3个关键点IOC 不直接创建对象先存定义BeanDefinition实例化和初始化是两回事实例化 造空壳初始化 赋值 增强AOP 代理在初始化后生成(3) IOC流程小结IOC 流程 定义 → 实例化 → 注入 → 初始化 → 缓存底层靠反射 缓存 Map 扩展接口2. DI依赖注入—— IOC 的实现方式通俗理解Spring 把对象创建好后自动把需要的依赖赋值给对象不用你手动 set。比如Service依赖DaoSpring 会自动把Dao注入给Service。IOC 是思想DI 是实现手段。3. AOP(1) 通俗解释不修改原有业务代码就能统一增强功能比如日志记录、事务管理、权限校验、性能监控(2) 底层原理动态代理不修改源码生成代理类增强方法JDK 动态代理基于接口CGLIB 代理基于类继承Spring 会在运行时生成代理对象在目标方法执行前后自动插入增强逻辑。责任链模式多个通知按顺序执行与 IOC 融合AOP 发生在 IOC 的初始化后阶段(3) 执行流行(两大阶段)第一阶段Spring 容器启动时生成代理对象这是IOC AOP 结合的关键步骤发生在 Bean 初始化过程中。极简流程加载切面 → 解析切点/通知 → Bean 初始化 → BeanPostProcessor 检测是否需要AOP → 生成JDK/CGLIB代理对象 → 代理对象存入Spring容器完整流程如下第 1 步解析 AOP 配置Spring 扫描你写的Aspect 切面类解析切点表达式哪些类、哪些方法需要增强解析通知类型Before/After/Around/AfterReturning/AfterThrowing第 2 步Bean 初始化进入 AOP 时机IOC 流程执行到BeanPostProcessor 后置处理→ 这里就是 AOP 生效的入口第 3 步判断是否需要创建代理Spring 检查当前 Bean 的方法是否匹配切点表达式不匹配 → 用原始对象匹配 → 进入代理创建逻辑第 4 步选择代理方式Spring 自动判断目标对象实现了接口→JDK 动态代理目标对象没有接口→CGLIB 动态代理第 5 步生成代理对象并放入容器Spring 把代理对象替换原始对象存入单例池。✅ 从此以后从容器拿的都是代理对象不是原始对象第二阶段代码调用方法时代理执行当你调用被增强的方法时执行该阶段流程。极简流程调用代理对象方法 → 执行通知链Around → Before → 目标方法 → After... → 返回结果完整流程如下第 1 步调用代理对象的方法第 2 步执行通知链拦截器链第 3 步AOP 标准执行顺序Around 环绕通知 前 → Before 前置通知 → 执行目标方法原始业务逻辑 → AfterReturning 返回通知 → After 最终通知 → Around 环绕通知 后如果发生异常Around 环绕通知 前 → Before 前置通知 → 执行目标方法抛出异常 → AfterThrowing 异常通知 → After 最终通知第 4 步执行目标方法第 5 步返回结果三、Spring Bean生命周期1.生命周期Bean 就是 Spring 管理的对象其生命周期一共 7 步①实例化调用构造方法创建空对象②属性填充DI 依赖注入③初始化前BeanPostProcessor 前置处理初始化前的扩展点④初始化依次执行PostConstruct注解方法、init-method⑤初始化后BeanPostProcessor 后置生成AOP代理对象⑥使用中正常业务调用⑦容器关闭触发销毁Spring 容器关闭时执行context.close()⑧执行销毁前方法依次执行PreDestroy注解方法、destroy-method/DisposableBean.destroy()⑨Bean被回收JVM 垃圾回收生命周期结束2. 需要注意的问题Autowired与Resource来源不同Autowired是Spring 官方提供Resource 是Java 官方JSR-250提供装配顺序不同Autowired先按类型byType装配找不到 → 报错找到多个 → 再按字段名匹配Resource先按名称byName装配找不到 → 再按类型byType装配Autowired常见问题Autowired 找到多个 Bean 为什么不报错因为按类型找到多个后会自动降级按字段名匹配名字匹配就不报错开发推荐用哪个纯 Spring 项目使用Autowired配合构造器注入最佳希望通用、跨容器使用Resource。企业开发主流使用Autowired实例化 vs 初始化实例化创建空对象初始化赋值 执行自定义方法AOP 发生在什么时候发生在Bean 后置处理器后置也就是初始化之后生成代理对象存入容器。初始化和销毁的执行顺序初始化PostConstruct→afterPropertiesSet→init-method销毁PreDestroy→destroy→destroy-method四、Spring整体工作流程加载配置XML / 注解 / JavaConfig扫描类识别Component等注解创建 Bean 实例IOC注入依赖DI生成代理对象AOP把 Bean 放入单例池Map缓存程序使用时直接从容器获取五、常见问题1. 单例 Bean 线程安全吗为什么不安全Spring 单例 Bean 默认不是线程安全的其原因是单例 Bean全局只有一个对象所有请求共用同一个对象如果有成员变量多线程会同时修改、互相覆盖导致数据错乱、业务异常2. 什么是有状态 / 无状态的Bean如果必须用有状态怎么解决(1)无状态 Bean安全 ✅不保存成员变量、不存储请求数据只提供方法不存数据每次请求都是新数据Service、Controller、Dao 都是无状态(2)有状态 Bean不安全 ❌类里定义了成员变量存储数据多线程并发访问会互相覆盖、数据错乱(3) 必须使用有状态Bean的3 种解决方案面试常问改成多例prototype每次获取新对象不共享使用 ThreadLocal 存放状态线程隔离最常用把变量放到 request/session 作用域3. Spring用到的设计模式有哪些这里只列出几种(1)工厂模式哪里用BeanFactory、ApplicationContext作用Spring 用工厂创建、管理 Bean不用自己 new(2)单例模式哪里用默认 Bean 都是单例作用全局只有一个对象存在singletonObjectsMap 中(3)代理模式AOP哪里用AOP 核心作用JDK 动态代理 / CGLIB 代理不修改源码增强方法(4)模板方法模式哪里用JdbcTemplate、RedisTemplate、RestTemplate作用固定流程可变部分交给子类实现(5)策略模式哪里用AOP 动态代理选择JDK / CGLIB作用根据条件选择不同实现(6) 责任链模式哪里用AOP 通知执行链、拦截器作用多个通知按顺序链式执行六、核心原理总结IOC对象交给 Spring 管理不用自己 newDISpring 自动给对象注入依赖AOP不改代码统一增强方法容器用 Map 存 Bean高效管理底层反射 动态代理