SpringBoot 自动装配原理详解
场景引入一个 Starter 后应用自动获得数据源或监控 Bean 很方便,但版本升级时也可能因类路径或配置变化加载了不同实现。 原理自动装配从启动注解导入候选配置类,再依据类路径、已有 Bean、属性和 Web 类型等条件筛选。它遵循“用户定义优先”的退让原则:许多默认 Bean 只在容器中尚不存在同类对象时创建。 设计步骤排查时先看依赖树和配置属性;开启条件评估报告,确认候选配置为何匹配或未匹配;检查 Bean 名称与类型覆盖;编写自定义 Starter 时拆分属性类、自动配置类和运行库,并用条件注解限定边界。 权衡自动装配降低接入成本,也把部分决策推迟到运行时;条件越灵活,组合测试越复杂。强行覆盖默认 Bean 能快速解决问题,却可能依赖内部实现,在框架升级时失效。 实践建议Starter 只提供合理默认值,不替业务做不可逆决定;属性设置前缀、默认值和校验,并生成配置元数据。使用 ApplicationContextRunner 测试有无依赖、不同属性和用户自定义 Bean 的组合。升级前比较条件报告,避免只看应用是否启动。 落地检查上线前还应做一次桌面演练:准备正常、...
MyBatis常见面试题总结
场景复杂查询需要精确 SQL 控制时,MyBatis 很合适;但参数拼接、结果映射、缓存和会话边界处理不当,也容易产生注入、N+1 或脏数据。 原理配置会把 Mapper 声明解析为映射语句,代理对象接收方法调用,经 Executor、StatementHandler、ParameterHandler 与 ResultSetHandler 完成执行和映射。SqlSession 非线程安全,一级缓存跟随会话,二级缓存跨会话且需谨慎维护一致性。 设计步骤先把 SQL 与参数契约写清,值使用 #{} 绑定,${} 只用于经过白名单的结构片段;复杂映射显式使用 resultMap;关联数据优先批量查询;事务由服务层定义;最后用执行计划、慢日志和真实数据量验证性能。 权衡MyBatis 可控且透明,但样板代码和 SQL 维护成本高;延迟加载减少初次查询,却可能隐藏 N+1;二级缓存降低读压,却在多表更新和分布式环境中带来失效难题;插件强大但会改变全局链路。 实践建议Mapper 保持无状态,分页必须有稳定排序;批处理控制批次和事务大小;大结果集使用游标并及时关闭资源。不要为了复用拼出难...
Spring常见面试题总结
场景面试或排障若只背 Bean、AOP、MVC 和事务的零散答案,很难解释它们在一次真实请求中如何协作。 原理请求先由 MVC 分发到控制器,再进入服务 Bean 的代理,切面可开启事务或记录指标,服务通过注入的仓储访问数据。Bean 生命周期决定依赖何时可用,作用域影响共享方式,异常类型和代理边界决定事务是否回滚。 设计步骤以一次下单请求画调用链;标注每个对象的创建者、作用域和代理类型;追踪参数绑定、校验、异常处理与响应;再模拟同类自调用、受检异常、并发访问和循环依赖,逐项验证实际行为。 权衡构造注入依赖明确且利于测试,但参数过多会暴露职责膨胀;单例节省创建成本,却要求无共享可变状态。声明式事务简洁,但跨线程、私有方法和未经过代理的调用不会自动获得语义。 实践建议回答问题时先给定义,再说明底层机制、失效条件和工程选择。项目中使用统一异常处理、类型安全配置与显式线程池。不要用 @Lazy 掩盖架构循环;事务方法保持清晰边界并指定回滚策略。能从请求链解释现象,才算真正掌握。 落地检查上线前还应做一次桌面演练:准备正常、边界、超时、重复与恶意输入,确认系统的返回、日志和指标彼此对...
Spring 中的设计模式详解
场景理解 Spring 只停留在注解用法,遇到扩展点时容易写出侵入式代码。把容器实现还原为设计模式,可以更准确地找到可替换位置。 原理BeanFactory 体现工厂与注册表,单例作用域由容器维护实例,AOP 使用代理,JdbcTemplate 固定资源管理骨架,事件机制使用观察者,HandlerAdapter 把不同控制器适配到统一调度流程,装饰器则逐层增强能力。 设计步骤阅读源码时先找稳定接口与变化实现;再追踪对象由谁创建、调用由谁转发、回调何时触发;用最小示例替换一个策略或适配器;最后验证生命周期、线程安全和异常传播,而不是背诵类名。 权衡模式让框架开放扩展而不修改核心,但多层代理、模板回调和事件监听会增加调试距离。同步事件简单可控,却耦合响应时间;异步事件解耦更强,却必须处理顺序、丢失与重试。 实践建议业务代码借鉴模式时保持克制:工厂集中创建,模板固定真正稳定的流程,事件表达已经发生的事实。不要复制 Spring 的通用复杂度。调试代理问题可先查看运行时类型和代理链;扩展框架优先使用公开 SPI,避免依赖内部类。 落地检查上线前还应做一次桌面演练:准备正常、边界、超时...
IoC & AOP详解(快速搞懂)
场景支付服务同时依赖仓储、风控和日志,如果对象自己创建依赖,替换实现与测试会很困难;若每个方法又手写事务和审计,业务逻辑会被横切代码淹没。 原理IoC 把对象创建和依赖装配交给容器,DI 是实现控制反转的主要方式。AOP 则在连接点应用通知,Spring 通常借助 JDK 动态代理或 CGLIB 包装 Bean,让事务、监控等逻辑围绕方法执行。 设计步骤先用接口或明确职责拆分依赖并采用构造注入;再识别真正跨多个模块的横切关注点;定义精确切点和执行顺序;确认调用必须经过代理;最后测试正常、异常和嵌套调用,观察代理类型及事务边界。 权衡IoC 增强替换性,却可能因 Bean 过多使依赖图复杂;AOP 减少重复,但隐藏控制流。切点过宽会误拦截,切面过多会造成顺序耦合。核心业务规则通常不应藏进切面。 实践建议依赖保持单向,出现循环依赖应重划职责而非依赖三级缓存“救场”。切面只处理日志、权限、事务等稳定横切能力,并输出可观测信息。自调用需要拆到独立 Bean 或改为显式编排,避免通过暴露代理制造更深耦合。 落地检查上线前还应做一次桌面演练:准备正常、边界、超时、重复与恶意输入,确认系统...
Async 注解原理分析
场景邮件、审计或报表生成不应阻塞主请求,但简单加上 @Async 后,可能出现注解失效、线程池耗尽、异常丢失和事务错觉。 原理Spring 通过后置处理器为目标 Bean 创建代理。外部调用进入拦截器后,任务被提交给 Executor,真正方法在工作线程运行;同类自调用绕过代理,因此不会异步。线程切换也意味着事务、ThreadLocal 和安全上下文不会天然继承。 设计步骤先确认任务允许异步且定义完成语义;配置有界线程池、队列、拒绝策略和线程名;从另一个 Bean 调用异步方法;需要结果时返回 CompletableFuture;显式传递上下文,并为超时、重试、幂等和异常告警设计处理链。 权衡异步缩短请求延迟,却没有减少总工作量;大队列看似避免拒绝,实则把故障变成长时间排队和内存压力。内存线程池实现简单,但进程重启会丢任务;可靠任务更适合消息队列或任务平台。 实践建议按任务类型隔离线程池,监控活跃线程、队列深度、拒绝数和耗时。不要依赖调用方事务提交后异步线程读取未提交数据,可在事务提交后发布事件。重要任务落持久化状态并支持补偿;只有可丢失的短任务才适合纯 @Async。 落地...
Spring & Spring Boot 专题:IoC、AOP、事务、自动装配、常用注解与源码
场景Spring 项目常能快速启动,但 Bean 来源、代理边界和自动配置条件不清时,循环依赖、事务失效及配置覆盖会在维护期暴露。 原理IoC 容器负责对象定义、创建、注入与生命周期,AOP 代理承载事务、异步和安全等横切逻辑。Spring MVC 组织请求链路,Spring Boot 再通过约定、条件装配和 Starter 降低配置成本。 设计步骤先按业务能力划分 Bean,使用构造注入显式表达依赖;再区分领域逻辑与 Web、持久化适配层;为横切功能确认代理调用边界;阅读条件评估报告理解自动配置;最后用切片测试和集成测试验证容器行为。 权衡容器管理提高组合能力,却隐藏对象创建过程;自动配置减少样板,也可能引入意外 Bean。AOP 避免重复代码,但调用路径更间接。便利与透明度之间需要通过清晰分层、日志和测试取得平衡。 实践建议避免静态获取 Bean 和字段注入;配置项建立类型安全绑定并校验;业务类保持无框架侵入的核心逻辑。遇到注解“不生效”,先检查对象是否由容器管理、是否经过代理、方法可见性与异常类型,再考虑修改框架配置。 落地检查上线前还应做一次桌面演练:准备正常、边界、...
Web 实时消息推送详解
场景进度通知、行情或协作编辑都希望服务端主动更新页面,但“实时”可能只要求几秒,也可能要求双向毫秒交互,方案不应一律 WebSocket。 原理短轮询周期请求,简单但有空转;长轮询保持请求到事件或超时;SSE 基于 HTTP 单向流并原生支持重连;WebSocket 建立全双工长连接;MQTT 以发布订阅和轻量协议适合物联网。连接层之外还需消息路由与状态管理。 设计步骤先量化延迟、方向、在线连接数和消息频率;单向通知优先评估 SSE,低频兼容场景用长轮询,强双向交互选 WebSocket;设计心跳、重连退避、事件 ID、鉴权续期;集群通过消息总线把事件路由到连接节点。 权衡长连接降低重复握手,却长期占用文件描述符和内存;WebSocket 灵活但代理、监控和背压更复杂。SSE 文本单向且浏览器连接数受限。保证至少一次投递会产生重复,精确一次通常代价过高。 实践建议消息携带单调序号或业务幂等键,客户端重连后从游标补偿;慢消费者设置缓冲上限并降级。负载均衡确认超时和连接迁移策略,监控在线数、重连率、积压和端到端延迟。先满足业务时效,再决定是否承担长连接复杂度。 落地检查上线前还应...
J2EE 基础知识
场景维护传统 Java Web 管理后台时,请求偶发串号、刷新后重复提交,问题往往不在语法,而在 Servlet 生命周期、转发与重定向、Cookie 与 Session 的边界没有理清。 原理容器只创建少量 Servlet 实例,却会用多个线程并发调用 service。request 保存单次请求数据,session 跨请求关联用户,application 面向整个应用;JSP 最终也会编译成 Servlet。转发复用同一次请求,重定向则让浏览器发起新请求。 设计步骤先画出浏览器、容器、Servlet 与会话存储的时序;再限定 Servlet 字段只放不可变依赖,把业务状态放到局部变量或外部存储;按查询与写入选择 GET、POST;最后为登录、跳转、刷新和并发请求补集成测试。 权衡Session 编程简单,却带来服务端状态、集群复制和过期治理;Cookie 易于横向扩展,但容量小且可能被窃取。转发少一次网络往返,却不会改变地址栏;重定向边界清晰,但要防止开放重定向。 实践建议不要在 Servlet 成员变量中缓存用户数据;写操作采用 PRG 模式避免刷新重放;Cookie ...
设计模式常见面试题总结
场景业务规则不断增加后,条件分支、对象创建和跨模块通知常纠缠在一起。直接套模式会增加类数量,完全不用模式又会让变化扩散。 原理设计模式是针对重复设计问题的协作词汇。工厂隔离创建,策略封装可替换算法,模板方法固定骨架,观察者传播事件,代理控制访问,适配器转换接口,单例约束实例数量。核心判断是哪个维度会变化。 设计步骤先找到真实坏味道与变化轴;再用最简单接口隔离它;通过测试固定现有行为;选一个能降低耦合的模式小步迁移;最后检查调用链、对象生命周期和失败传播是否比原来更清晰。 权衡模式带来扩展点,也增加间接层。策略适合算法频繁切换,只有一个实现时可能过度;观察者解耦发布者,却使时序和异常更难追踪;单例访问方便,但隐藏依赖并影响测试。 实践建议从问题出发,不从模式名称出发。扩展点至少出现两种现实变化再抽象;事件携带最小稳定事实并配置追踪;对象创建集中但不要形成万能工厂。评审时要求说明移除模式会造成什么具体成本,答不出来通常意味着尚未需要。 落地检查上线前还应做一次桌面演练:准备正常、边界、超时、重复与恶意输入,确认系统的返回、日志和指标彼此对应;在预发布环境模拟依赖不可用、进程重启和...