AI写代码时代,为什么还要学设计模式、Spring源码和JVM
2026/9/16 23:43:22 网站建设 项目流程

最近几次直播答疑,被问到最多的问题已经从"怎么学设计模式"变成了"AI 都能写代码了,还要学设计模式、Spring 源码和 JVM 吗"。问的人里有刚上大二的学生,也有工作了三五年的后端开发。有个工作三年的朋友尤其典型:他刚用 AI 把一个部门内部管理系统搭起来,Controller、Service、Mapper 一气呵成,跑得还挺正常。他跟我说"我感觉自己不用再啃底层了"。我反手给他抛了一个问题:如果这段代码上线后出现事务不生效、接口突然变慢、GC 不停,你打算怎么定位?他愣了几秒。

这篇文章,就是要把这个问题彻底聊透。我的答案很明确:要学,但学的目的和方式都变了。不是让你继续背八股,而是让你在 AI 写出每段代码时,都能保留住"判断它到底行不行"的能力。

1. 先说结论:要学,但不是用过去的方式学

1.1 能写代码和会写代码,是两件事

先把概念掰清楚。AI 能写代码,指的是它对描述性的需求给出可运行的实现,擅长把通用场景翻译成代码。但"会写代码"是另一回事:你知道这个需求为什么要这样建模,知道这段代码在特定数据规模下会怎样表现,知道线上告警来了该看哪台机器的哪个指标。

打个比方,前者是照着菜谱炒菜的学徒,后者是知道为什么先炒糖色、什么时候必须大火爆炒的厨师。学徒做一百道菜可能都不会糊,菜谱也是 AI 给的,但菜一旦出问题,学徒只能拍照发给 AI 问"哪里错了";厨师却能看颜色、闻气味、掂锅铲,就能判断是火候不对还是食材出了问题。

用一张表把两种状态的差异列出来,很多人看完就明白问题出在哪了:

维度能写代码会写代码
需求理解能根据描述生成代码能拆解模糊诉求、识别需求冲突
技术选型自动套用常见最佳实践根据项目阶段和团队情况做取舍
运行行为能编译能运行能预判内存、并发、性能问题
故障定位搜索报错、反复试错从原理出发一路逆推
代码演化版本越叠越乱知道何时该拆、何时该抽象

这张表不是要贬低 AI,而是说明 AI 的输出只是半成品。现在的 AI 写 CRUD 确实比大多数人快,但业务里真正的难点——复杂的权限模型、分布式事务边界、高性能批处理——从来不是靠"描述得清楚一点"就能解决的。

1.2 底层知识决定了你能审查 AI 到什么深度

AI 生成的代码本质上是基于概率的拼装,不是基于理解的推演。它见过海量开源代码,知道"支付"一般会配一个 Strategy 接口,但它不知道你的业务变化点在哪里。它给你写出的代码,经常是"看起来合理",而不是"在你的场景下合理"。

谁来做这个判断?只能是你。

如果你不懂设计模式,就会把所有带 Strategy 命名的代码都当合规;如果你不懂 Spring 源码,就不知道 @Transactional 是不是真的被代理链路接住了;如果你不懂 JVM,就只能在 OOM 之后把堆内存往上调,靠运气扛过上线。

底子决定你能在 AI 面前保留多少判断力。在一个 AI 能用十分钟写完一周需求的世界里,剩下的人力价值就是审查、纠偏、兜底。这也是为什么现在招聘市场上,能说清楚底层原理的 JD 反而越来越多——不是面试官古板,是因为团队真的很需要一个能对 AI 产出负责的人。

2. 设计模式:AI 生成代码的质检标准

2.1 AI 把策略模式写成了 if-else 换皮,你看得出来吗

来一个特别典型的例子。我让 AI 写"用策略模式实现不同支付方式的处理",它很快给了一版。核心逻辑长这样:

PaymentStrategy strategy = null; if ("alipay".equals(type)) { strategy = new AlipayStrategy(); } else if ("wechat".equals(type)) { strategy = new WechatPayStrategy(); } else if ("card".equals(type)) { strategy = new CardStrategy(); } Context context = new Context(strategy); context.execute();

如果只背过 UML 图,你会觉得这代码挺标准:有 PaymentStrategy 接口,有多个实现类,有 Context 持有策略。但实际这跟策略模式的初衷相去甚远。策略模式的核心不是"我用了接口",而是"客户端依赖抽象,策略的选择与使用被解耦,将来加一种支付方式不需要改客户端逻辑"。

你看这段代码,新增一个支付方式,还是要跑到客户端代码里多加一个 else if,这本质上还是面向实现编程,只是换了身策略模式的衣服。

再看一个更隐蔽的问题:很多 AI 生成的 Context 里还会带着 switch 去判断具体策略,这就是把简单工厂模式和策略模式混着用了。简单工厂解决的是"创建谁"的问题,策略解决的是"怎么执行"的问题,它们可以配合,但职责要分开。你让 AI 写一版,它因为训练数据里两种写法出现频率都不低,很可能把两者揉在一起,生成一个不伦不类的中间产物。

你如果不懂模式背后的变化点和职责,根本看不见这种"污染"。AI 自己更不会主动告诉你"我这段写复杂了"。所以设计模式在这时候不是知识,是质检工具。

2.2 设计模式是描述"变化"的语言,不是背 UML 图

我见过太多人把设计模式当期末考试背:抽象工厂有哪些角色、观察者模式和发布订阅有什么区别。但设计模式真正的作用,是提供一套描述"变化将要发生的位置"的语言。业务里最会变化的地方,就是你该用模式的地方。

订单价格计算要加折扣、推送通知要多渠道、状态流转越来越复杂——这些场景背后是策略、观察者、状态模式。你没有这套词汇,对着 AI 就只会说"帮我写一个订单模块";有了这套词汇,你会说"订单这块用策略模式封装价格计算,后续我要支持叠券、积分抵扣,注意别在调用方堆 if-else"。AI 接收到后给出来的代码,质量完全不一样。

再往深一层,设计模式对你自己的价值,是形成一种"坏味道嗅觉"。看到一个类越来越胖、一堆 if-else 循环嵌套、新需求一来就要连改好几个类,你能下意识地问:这里是不是应该用组合代替继承?是不是可以引入模板方法?这个嗅觉 AI 没有。AI 可以帮你写出重构后的版本,但要不要重构、哪一段需要重构、重构的边界在哪,还是得靠你的判断。

2.3 用 AI 学设计模式的三条高效路径

第一条,坏味道驱动。自己先用最朴实的方式写一个功能,比如不同会员等级打不同折扣。看看扩展新等级时要改哪里,那个"改得很痛"的地方就是模式的出生点。让 AI 帮忙分别生成"普通实现"和"策略模式实现",再对比哪个更符合开闭原则。这种对比远比看十篇设计模式讲解印象深刻。

第二条,让 AI 做模式横评。把同一个需求丢给 AI,要求它分别用简单工厂、工厂方法、策略模式、模板方法实现,并列出每种模式在增加新需求时的改动范围。这个练习能让你快速建立"模式之间的边界感"。实践下来你会发现,AI 的横评结果不一定全对,但恰好是你纠正它、加深理解的机会。

第三条,对 AI 生成代码做模式审查。让 AI 写一段业务代码后,你拿着设计原则一个个 check:有没有违反单一职责?有没有一处修改要波及多个类?开闭原则守住没有?审查完再命令 AI 重构。这个过程本质是在练自己的审稿能力,练熟了面试时也不会再怕"结合项目讲设计模式"这种题。

3. Spring 源码:AI 生成 Spring 项目后的找坑地图

3.1 事务不生效、代理失效:为什么 AI 救不了你

AI 生成 Spring Boot 项目的能力是真的强,搭个 web 服务带 CRUD,几分钟的事。但麻烦也来了:项目一上线,问题全不是 AI 能回答的。最常见的一个,就是 @Transactional 不生效。

AI 给你写了一个 UserService,注册方法上标了 @Transactional,里面先插用户再发积分,结果发积分抛异常后用户还是写进去了。你把这行代码复制给 AI 问为什么,它可能给你列一堆排查方向,但你得快速判断哪些靠谱,而不是挨个试。

我带你快速捋一下根因。Spring 事务依赖 AOP 代理,@Transactional 要被 TransactionInterceptor 拦截,前提是这个方法是通过代理对象调用的。如果在一个 Bean 内部,用 this 直接调用同类里的另一个事务方法,调用发生在目标对象内部,根本没经过代理,事务自然失效。

要修复,要么把两个方法拆到不同 Bean,通过注入的代理跨 Bean 调用;要么用 AopContext.currentProxy(),或者用自注入。但你注意到没有,这个修复方案的每一步,都要求你懂得 Spring 是怎么创建 Bean、怎么生成代理的。不知道这些,你连"发生在哪个环节"都说不清,只能像个无头苍蝇一样改配置。

这类问题非常多。再比如你让 AI 写一个原型作用域的 Bean,然后用 @Autowired 注入到单例 Bean 里,你会发现每次拿到的都是同一个实例。原因是单例 Bean 在初始化时就把依赖注进去了,Autowired 按类型找到了那个原型 Bean,并不会因为你标注了 prototype 就每次给你新的。解决办法是用 ObjectProvider 或者 @Lazy 来延迟获取。

这个知识点在 Spring 源码的依赖注入阶段体现得特别清楚。你不看源码,靠文档也能解决,但出问题时容易把原因归到"Bean 作用域"之外的地方,然后绕一大圈远路。

3.2 主线阅读法:别从 Github 克隆源码开始

很多人一听读 Spring 源码,就觉得要 clone 整个 Spring Framework 仓库,从 IoC 容器一行行往下读。我劝你别这么干,这么读大概率一周就放弃了。Spring 源码的读法应该是以问题为主线,用"最小启动 Demo + 断点"去确认主流程,再顺着边界展开。

第一步,建一个最简单的 Spring Boot 项目,只放一个 @Configuration 和一个 @Bean,在 AbstractApplicationContext.refresh() 的各个阶段打上断点:BeanDefinition 的加载、BeanFactoryPostProcessor 的执行、普通 Bean 的实例化、AOP 代理的创建。跟着断点走一遍,你会建立起一条很粗的主线:配置类解析成 BeanDefinition,BeanDefinition 被实例化成 Bean,实例化之后做属性填充、初始化、代理增强。

主线有了,后面所有问题都是在这条线上的某个环节插入的。

第二步,带着真实问题去点源码。比如事务不生效,就顺着 @EnableTransactionManagement 找 TransactionInterceptor,再找 AbstractAutoProxyCreator,看它怎么为 Bean 生成代理。看的过程中不需要把每个类的每个方法都读完,只需要抓住"谁在什么时候给哪个 Bean 创建代理"这个核心。等你能用自己的话把这条链路讲清楚,Spring AOP 这块的面试题基本难不住你。

3.3 让 AI 帮你读源码,但最终用源码验证 AI

AI 在 Spring 源码学习里真的有用,但用法要小心。你可以让 AI 帮你看开源代码,比如"请用通俗语言解释 DefaultSingletonBeanRegistry 的 singletonObjects、earlySingletonObjects、singletonFactories 三级缓存是干嘛的",它能讲得比大部分教程都好。

问题在于它对具体版本的细节容易出错,经常会一本正经地把 AOP 处理时序讲错。所以我的经验是:把 AI 的讲解当预习和提示,真正的结论必须自己打开对应版本的源码确认。

这个过程看起来慢,其实是最快的——你既不会被海量代码劝退,也不会被 AI 带进沟里。我常用的一个组合是:让 AI 输出某条调用链的关键方法列表,我照着列表在 IDE 里逐个打开源码,打断点跑一遍,确认哪个类、哪个方法在哪一步真正生效。AI 负责快速圈出可能相关的代码块,我负责做最终的判断和验证。这种"AI 开导航、我踩油门"的学法,是 AI 时代读源码的最优解。

4. JVM:AI 生成的代码上线前的最后一道关口

4.1 OOM 和 GC 飙升,AI 能写代码但不会背锅

JVM 这块更现实。AI 写代码,逻辑上可能很完整,但它不知道你的线上机器有多少内存,不知道你的接口要求的响应时间是 200ms 还是 2s,更不知道你的数据量会从一万涨到一千万。它写出来的代码,经常会在运行时给你爆冷。

举个我最近帮同事看的例子。AI 生成的一个批量处理任务,把数据库查出来的所有记录都塞进一个 ArrayList,然后循环处理。本地测试只有几千条数据,毫无感觉;上线跑了三个月,数据量到几百万,接口突然频繁 Full GC,最后直接 OOM。

同事一开始想的是"把堆调大点",这其实是很多人的第一反应。但真正的问题不是堆不够大,而是代码在无意识地把海量数据一次性加载到内存,GC 跟不上这种对象的持续创建。正确的做法应该是分页读取、流式处理、限制每批的处理量。能做出这个判断的前提,是你理解堆内存的分配方式、对象的存活周期、GC 的触发条件。

你可以现在就用jstat -gcutil <pid> 1000去看自己开发机上某个 Java 进程的 GC 情况。然后让 AI 帮你解释每一列的含义。你会发现,如果你不知道 Young GC、Old GC、Full GC 的区别,连 AI 解释你都听得半懂不懂。这就是为什么我说,JVM 不是只在面试的时候考的,它是线上事故现场的通用语言。

4.2 从"堆内存不足"这类小坑看懂 JVM 参数

有些人可能觉得 JVM 调优是架构师的事,但日常开发里 JVM 参数就够让人头疼了。最常见的场景是:Gradle 构建大型 Java 项目时,构建守护进程报出expiring daemon because jvm heap space is exhausted。很多人看到这个报错,第一反应是照网上帖子把 -Xmx 往大了调。

但如果你理解了 Gradle daemon 是一个长期运行的 JVM 进程,所有构建任务复用它,你就会意识到:堆内存不够,不只是因为项目大,还可能是构建过程中加载了过多依赖、worker 进程之间互相抢占资源。正确做法是在 gradle.properties 里显式设置org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m,并评估是调大 daemon 内存,还是把项目拆模块、减少并发任务。

IDEA 里同理,很多人问"IDEA 分配 4G 内存还是卡",如果你理解 IDE 本身也是一个 Java 进程,界面卡顿经常不是堆不够,而是元空间不足或 GC 停顿太长,就不会只会去加 -Xmx 了。多了解一些-XX:MetaspaceSize-XX:+UseG1GC这类参数的含义,你会更清楚怎么调。

这里我不打算罗列参数大全,只想说一句:这些日常踩到的小坑,恰好就是学 JVM 的最佳入口。AI 可以帮你解释参数,但它不知道你的项目会不会遇到同样的问题,这个判断最终是你的。

4.3 以诊断为目标学 JVM,比背面试题高效得多

面试题里的 JVM 内存模型、GC 算法、类加载机制,看起来离日常很远。其实每一个知识点都能对应一类线上症状。我自己给团队培训时用的对照逻辑是这样的:

线上症状对应 JVM 知识点常用排查工具
内存溢出堆内存分配、GC Rootsjmap、MAT
CPU 持续飙升线程栈、锁竞争jstack、Arthas
Full GC 频繁对象晋升、GC 算法jstat、GC 日志
启动特别慢类加载机制、元空间-verbose:class

用这样一张"症状-知识-工具"对照表来学,比单纯背《深入理解 Java 虚拟机》快多了。AI 这时候也能帮忙:你把一段 GC 日志扔给 AI,让它解释每个字段,再让它推测可能瓶颈。但最后你必须自己用工具复现一遍,确认它的解释和实际日志是否吻合。JVM 这种东西,AI 的文本能力和工程现实之间还隔着一层"上下文",只有你亲手把 dump 文件打开看过,才能建立真正的体感。

5. AI 时代的组合打法:让 AI 当陪练而不是代写

5.1 三组提示词技巧,把 AI 变成"水平很差的实习生"

既然离不开 AI,那就琢磨怎么用。我的核心观点是:别把 AI 当最终答案,把它当"水平很差的实习生"。它干活快、知识面广,但经常不理解你的业务,也不会为结果负责。你要做的是给它布置任务、审查结果、验收返工。

这个模式下,三组提示词特别好用。

第一组,模式对比型:"请用不同设计模式解决同一个需求,列出每种模式在新增需求时的改动范围、适用场景、潜在坏味道。"这比直接问"什么是策略模式"有效十倍。AI 给出的对比就是一份现成的学习材料,你只需要验证它说得对不对。

第二组,调用链拆解型:"请把 Spring Bean 创建和 AOP 代理生成的关键调用链列出来,并解释每个环节可能出错的地方。"拿到之后,用 IDE 打断点验证。AI 负责把它见过的常见实现讲给你听,你负责确认当前版本是不是这样。

第三组,日志解读型:"请解释这段 GC 日志的每个字段,并给出诊断步骤。"然后用工具实测。AI 的推断可以当预判,但最终要以实际日志为准。

这三组提示词的共同点是:AI 负责产出"候选答案",你负责"验证和裁量"。裁量权在你手上,底层知识就是你行使裁量权的依据。这么练上几轮,你会发现自己的判断力提升速度,比单纯看教程快得多。

5.2 AI 生成 + 设计模式审查 + Spring 定位 + JVM 验证的工作流

我现在带项目,基本所有第一版代码都让 AI 写,但完整工作流会多出三个关键动作。

第一步,AI 生成完业务代码,我先做设计模式审查:看它有没有违反开闭原则、有没有把策略和工厂混用、有没有在不需要抽象的地方强行抽象。审查通过,才进入联调。

第二步,Crash 或行为诡异时,直接切到 Spring 视图:这个 Bean 是什么时候创建的?谁调的它?经过 AOP 代理没有?事务拦截器在哪一层生效?定位方式不是搜报错,而是顺着主流程看。

第三步,部署前和上线后,用 jstat、GC 日志、压测结果做 JVM 验证,确认代码在真实负载下的内存表现,再决定要不要改实现或调参数。

这套流程跑下来,你会发现 AI 极大地提升了编码效率,但设计模式、Spring 源码、JVM 这些底层知识,反而成了整个团队的护城河。没有这些底子的团队,AI 生成得快,事故也来得快;有这些底子的团队,AI 生成得快,交付得更快。以后 Spring Cloud、Spring AI 这些生态只会把工程复杂度推得更高,底层认知的价值只增不减。

6. 不同阶段开发者的学习优先级

6.1 在校学生:先把根基扎稳,AI 只是沙盘

如果你是学生,我的建议非常朴素:不要用 AI 把作业一抄完事。作业里包含的 CRUD、小项目,是你手感养成的重要来源。设计模式课不要只背期末考试,挑三个常用模式(策略、模板方法、观察者)亲手实现一遍,再用 AI 做变体对比。

Spring 源码不用全读,但至少要跟着一个简单 demo 把 Bean 生命周期跑一遍。JVM 以内存模型和 GC 概念为主,学会用 jstat 看懂普通 Java 进程的 GC。这三样东西一旦地基没打好,工作后还债的成本是现在的三倍不止。

同时学生有一个独特优势:时间多、试错成本低。你可以让 AI 生成一段"故意写坏"的代码,然后自己去调。这种沙盘式的练习,比 AI 直接给出标准答案有用得多。等你在调试中撞过几次墙,设计模式和 JVM 就不再是抽象概念了。

6.2 初级/中级开发:用问题清单驱动,AI 是加速器

工作前五年,人的精力是有限的,别想着把 JVM、Spring 源码、设计模式全学透。更高效的做法是搞一本"线上问题清单":凡是你在项目里踩过的坑,都记录一下对应的技术点。

事务不生效,去查 AOP;Bean 循环依赖,去查三级缓存;接口 OOM,去查堆和 GC。AI 在这里的作用是把第一版代码写完,省下来的时间全部用来复盘问题,让每个坑都变成一次底层知识的实战练习。

当你手里有几十个这样的案例时,设计模式、Spring 源码、JVM 的很多内容就不再是抽象名词了,而是你亲身解决过的地图点。面试的时候,你说出的每个知识点都带着真实背景,这种说服力是背八股给不了的。

6.3 资深/架构师:把三座大山升级成决策工具

如果你是架构师或者准备往架构走,这三样东西的意义又不一样。设计模式要升级成领域建模和业务架构语言,你要能用它指导团队把易变部分隔离出来。

Spring 源码要升级成开源组件评估和扩展点设计能力,你要能在选型时判断某个框架的扩展性是否满足未来需求。JVM 要升级成容量规划和性能管理工具,你要能说清系统在什么数据规模下该用 G1 还是 ZGC,该预留多少堆内存,扛不住时是加机器还是改代码。

AI Agent 以后会承担越来越多的工程实现,而架构工程师的职责,恰恰是定义好 Agent 的行为边界、验收标准和回滚方案。这些决策背后,设计模式、Spring 源码、JVM 依旧是底层支撑。

最后说点个人体会。最近半年带项目,我发现一个挺残酷的现实:能用 AI 五倍速写代码的人越来越多,但能扛住线上事故、能解释清楚"为什么这么设计"的人,还是那么少。前者是 AI 的操作员,后者才有资格当 AI 的技术负责人。

所以我回答所有来问我的朋友:要学,而且要趁早学,只是学习的方式要换成"和 AI 打配合"。我自己的习惯是让 AI 先写、我后审,每审出一个问题,就往下挖一层原理,直到能用大白话讲清楚。如果你也想试试,明天打开 AI 生成第一段代码时,不要急着复制粘贴,先问它一句:你为什么要这样写?等你能回答这个问题的时候,你就不需要再问别人要不要学设计模式、Spring 源码和 JVM 了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询