
AI 写 Java 代码最危险的,不是写错,而是没有门禁
这段时间,很多 Java 开发者已经开始习惯让 AI 参与写代码了。
以前我们用 AI,大多是让它解释一段代码、生成一个 DTO、补一个 Controller、写一个简单的 SQL。现在不一样了,Claude Code、Cursor、Codex 这类工具已经能直接进入项目目录,读取文件,修改代码,执行命令,甚至在一个 Spring Boot 项目里连续完成一轮开发任务。
这确实很强。
但用得越多,我越发现一个新的问题:AI 写代码的能力越强,团队反而越需要“门禁”。
因为过去一个开发者改代码,是一步一步来的。你会打开文件,看一眼上下文,改几行,跑一下测试,再看一下 diff。速度不算特别快,但过程是可控的。现在 AI 不一样,它可以在很短时间内改多个文件,顺手调整配置,补测试,跑命令,甚至为了让任务完成,去动一些你原本并不想让它动的地方。
这时候真正危险的,不是 AI 写错一行代码。
写错一行代码并不可怕,编译能发现,测试能发现,review 也可能发现。更危险的是:AI 在没有边界的情况下,改了不该改的文件,执行了不该执行的命令,绕过了团队原本应该有的检查。
比如它为了修一个接口问题,顺手改了common-core;为了让测试通过,改了生产逻辑;为了初始化环境,执行了一个危险脚本;为了调整配置,动了application-prod.yml;为了清理临时文件,执行了带删除风险的命令。
这些问题,才是 AI Coding 真正进入真实项目以后必须面对的风险。
所以,今天这篇文章想聊的不是“AI 能不能写代码”,也不是“哪个工具更强”,而是一个更接近工程落地的问题:
当 AI 开始改 Spring Boot 项目时,我们能不能给它加一道自动门禁?
Java 项目最怕的不是 AI 改慢,而是 AI 改得太快
传统 Java 项目之所以难改,往往不是因为代码写不出来,而是因为边界太多。
一个看似普通的接口改动,可能会牵扯 Controller、Service、Mapper、DTO、VO、XML、缓存、MQ、权限、事务和测试。你改一个订单字段,可能影响前端展示;你改一个状态枚举,可能影响历史数据;你改一个公共方法,可能影响多个服务;你改一个配置文件,可能影响不同环境的启动行为。
有经验的 Java 开发者在改代码时,脑子里其实一直有一套隐形规则。
哪些文件可以动,哪些文件不能轻易动;哪些模块属于核心链路,哪些模块只是边缘功能;哪些测试必须跑,哪些配置不能改;哪些改动需要人工确认,哪些改动可以直接提交。
这些规则,很多时候不是写在代码里的,而是团队经验。
问题是,AI 并不天然知道这些经验。
如果你只是告诉它:
帮我修复订单退款接口的问题。
它可能会根据当前上下文选择一条“看起来最合理”的路径。但这条路径不一定符合你们团队的工程规范。尤其是 Claude Code 这类可以读文件、改文件、执行命令的工具,一旦没有门禁,执行力越强,风险也越大。
这就是我现在越来越强调“AI 自动门禁”的原因。
AI 可以写代码,但不能没有护栏。
什么是 AI 自动门禁?
所谓 AI 自动门禁,不是让 AI 每次都问你一句“我能不能改这个文件”。如果所有动作都靠人工确认,那效率会很低,也很容易变成形式主义。
更合理的方式,是把一些确定性的工程规则自动化。
比如,只要 AI 尝试修改生产配置文件,就自动拦截。
只要 AI 尝试执行危险删除命令,就自动拒绝。
只要 AI 修改了 Java 文件,就自动提醒需要跑对应模块测试。
只要 AI 修改了 Mapper XML,就自动提醒检查 SQL 风险。
只要 AI 修改了订单、支付、库存相关代码,就自动要求输出影响范围。
这类规则不应该每次靠你在提示词里重复强调。因为只靠提示词,最大的问题是不稳定。你今天写了,明天可能忘了;这个任务写了,下一个任务可能漏了;这个 Agent 遵守了,另一个 Agent 可能没遵守。
真正稳定的工程规则,应该进入工具层。
在 Claude Code 里,这类能力就可以通过 Hooks 来做。
你可以把 Hooks 理解成 Claude Code 执行过程里的“自动检查点”。当 Claude Code 准备执行某个工具、修改某个文件、完成某个任务、等待用户输入时,Hooks 可以自动运行你定义的脚本或命令。
这就给 Java 项目提供了一个很有价值的能力:不再完全依赖 AI 自觉,而是用工程规则约束 AI 行为。
为什么 Hooks 对 Spring Boot 项目很有价值?
Spring Boot 项目非常适合加 Hooks,因为它有很多明确的工程边界。
比如生产配置文件通常不能随便改:
application-prod.ymlapplication-prod.yamlbootstrap-prod.yml
公共模块不能随便改:
common-corecommon-securitycommon-web
核心业务模块不能直接大改:
order-servicepayment-serviceinventory-service
敏感命令不能随便执行:
rm -rfdrop databasetruncate tableredis-cli flushalldocker volume rm
这些规则不需要 AI 判断,也不需要模型推理。它们本来就是确定性规则。既然是确定性规则,就应该交给 Hooks 这种机制自动处理。
举个例子,如果 AI 想执行:
rm -rf /tmp/build在某些场景下可能没问题,但如果它执行的是:
rm -rf .或者:
redis-cli flushall那就非常危险。
再比如 AI 想修改:
src/main/resources/application-prod.yml如果任务只是修一个订单接口,它根本不应该碰生产配置。这个动作应该被自动拦住,至少要让开发者明确确认。
这就是 Hooks 的意义。
它不是让 AI 更聪明,而是让 AI 更守规矩。
第一道门禁:拦住危险命令
如果一个 AI Coding 工具可以执行终端命令,那么第一道门禁一定是命令安全。
因为代码写错可以 review,命令执行错了可能直接造成破坏。尤其是在本地连接了数据库、Redis、Docker、云服务 CLI 的环境里,危险命令必须被限制。
在 Claude Code 里,可以通过PreToolUse这类 Hook 在工具执行前进行检查。比如当 Claude Code 准备执行 Bash 命令时,先把命令交给一个脚本判断,如果命中危险规则,就直接阻止。
可以准备一个类似这样的脚本:
# .claude/hooks/block-dangerous-command.pyimport jsonimport reimport sysdata = json.load(sys.stdin)tool_input = data.get("tool_input", {})command = tool_input.get("command", "")danger_patterns = [r"rm\s+-rf\s+/",r"rm\s+-rf\s+\.",r"drop\s+database",r"truncate\s+table",r"redis-cli\s+flushall",r"docker\s+volume\s+rm",r"kubectl\s+delete",]for pattern in danger_patterns:if re.search(pattern, command, re.IGNORECASE):print(f"Blocked dangerous command: {command}", file=sys.stderr)sys.exit(2)sys.exit(0)
然后在 Claude Code 的项目配置里,把它挂到 Bash 执行前:
{"hooks": {"PreToolUse": [{"matcher": "Bash","hooks": [{"type": "command","command": "python3 .claude/hooks/block-dangerous-command.py"}]}]}}
这类脚本不需要很复杂,但价值非常大。它相当于告诉 AI:你可以执行命令,但不能越过安全红线。
对 Java 项目来说,这一步尤其重要。因为很多 Spring Boot 项目本地会连接开发数据库、测试 Redis、Docker Compose、K8s 环境,AI 如果不小心执行了危险命令,影响会比改错代码严重得多。
第二道门禁:保护生产配置文件
很多 Spring Boot 事故,都和配置有关。
比如数据库连接、Redis 地址、MQ Topic、鉴权配置、支付回调地址、日志级别、线程池参数、限流配置。这些东西一旦被误改,问题可能不会马上在编译期暴露,而是到启动、联调甚至上线后才出现。
AI 改代码时,也很容易为了“让项目能跑起来”去改配置文件。
这在 demo 项目里可能无所谓,但在真实项目里非常危险。
所以第二道门禁,应该是保护生产配置文件。
比如只要 Claude Code 尝试修改:
application-prod.ymlapplication-prod.yamlbootstrap-prod.ymlbootstrap-prod.yaml
就应该自动拦住,或者至少提示必须人工确认。
可以写一个文件保护脚本:
# .claude/hooks/protect-prod-config.pyimport jsonimport sysdata = json.load(sys.stdin)tool_input = data.get("tool_input", {})file_path = tool_input.get("file_path", "")protected_files = ["application-prod.yml","application-prod.yaml","bootstrap-prod.yml","bootstrap-prod.yaml",]if any(file_path.endswith(name) for name in protected_files):print(f"Blocked editing protected config file: {file_path}", file=sys.stderr)sys.exit(2)sys.exit(0)
然后把它挂到文件编辑前:
{"hooks": {"PreToolUse": [{"matcher": "Edit|Write","hooks": [{"type": "command","command": "python3 .claude/hooks/protect-prod-config.py"}]}]}}
这样,AI 不是不能改配置,而是不能在没有明确授权的情况下改生产配置。
这就是门禁的核心思想:不是完全禁止 AI,而是把高风险动作从“默认允许”变成“必须确认”。
第三道门禁:修改 Java 文件后,提醒必须验证
AI 修改 Java 文件以后,最容易出现的问题是:代码看起来改完了,但没有跑测试。
这在真实项目里很常见。AI 可能会告诉你“我已经完成修改”,但它不一定真的跑了对应模块的测试。即使跑了,也可能只跑了某个非常局部的命令。
对 Spring Boot 项目来说,只要改了 Java 文件,至少应该触发验证意识。
比如修改了order-service,就应该提示运行:
mvn -pl order-service test如果是多模块 Maven 项目,还可能需要加上:
mvn -pl order-service -am test这里不一定要每次自动跑完整测试。因为大型 Java 项目跑测试可能很慢,频繁自动跑会影响效率。更合理的做法是:Hooks 可以在检测到 Java 文件变更后,自动输出提醒,或者记录需要验证的模块,最后在任务结束时统一提示。
比如检测文件路径里是否包含.java,然后输出提醒:
# .claude/hooks/java-change-reminder.pyimport jsonimport sysdata = json.load(sys.stdin)tool_input = data.get("tool_input", {})file_path = tool_input.get("file_path", "")if file_path.endswith(".java"):print(f"Java file changed: {file_path}. Remember to run related Maven tests.", file=sys.stderr)sys.exit(0)
这个 Hook 不一定拦截 AI,但它能让验证变成一个固定动作,而不是靠人临时想起来。
真实团队里,很多问题不是没人知道要跑测试,而是太容易忘。
Hooks 的价值,就是把这些“应该做”的事情变成自动提醒。
第四道门禁:Mapper XML 变更后,提醒检查 SQL 风险
对于 MyBatis 项目来说,Mapper XML 是非常高风险的地方。
AI 修改 Java 代码时,错误通常比较容易通过编译发现。但 XML 里的动态 SQL,一旦写错,可能编译期完全没问题,运行时才出问题。
比如:
条件判断写错。
字段名写错。
时间范围漏掉。
分页条件不生效。
动态 SQL 导致全表扫描。
foreach处理空集合异常。
新增查询缺少索引。
这些问题都很真实。
所以如果 AI 修改了:
src/main/resources/mapper/*.xml最好自动提醒开发者进行 SQL 风险检查。
比如:
# .claude/hooks/mapper-change-reminder.pyimport jsonimport sysdata = json.load(sys.stdin)tool_input = data.get("tool_input", {})file_path = tool_input.get("file_path", "")if file_path.endswith(".xml") and "/mapper/" in file_path:print("Mapper XML changed. Please check dynamic SQL, indexes, pagination, and empty collection handling.",file=sys.stderr,)sys.exit(0)
这类提醒看起来很简单,但对 Java 团队非常实用。
因为 AI 很容易写出“语法上看起来没问题”的 SQL,但 SQL 的性能风险和边界风险,需要额外检查。
尤其是订单列表、用户列表、交易流水、日志查询这类大表查询,不能只看功能是否能跑,还要看是否可能拖垮数据库。
第五道门禁:核心链路改动后,必须输出风险说明
对于订单、支付、库存、权限这类模块,只提醒跑测试还不够。
这些模块属于核心链路,修改后必须说明影响范围。
比如 AI 修改了:
order-servicepayment-serviceinventory-servicecommon-security
那么任务结束时,应该强制要求输出:
修改了哪些核心逻辑。
是否影响接口契约。
是否影响事务边界。
是否影响 MQ。
是否影响 Redis 缓存。
是否影响历史数据兼容。
是否需要人工二次确认。
这类事情不一定完全靠脚本判断,但可以通过 Hooks 或项目规则把它变成固定流程。比如在Stop阶段做一个检查,如果本轮改动涉及核心目录,就提醒必须补充风险说明。
这比事后人工追问要稳定。
因为 AI 经常会在完成任务时给出一个很乐观的总结:
“已完成修改,并通过测试。”
但真实项目里,我们更关心的是:
改动影响了什么?
有没有潜在风险?
哪些地方需要人工确认?
这才是 Java 后端团队真正需要的交付结果。
Hooks 和提示词不是替代关系
这里有一点很重要。
有了 Hooks,并不代表不需要提示词。
提示词负责告诉 AI 当前任务要做什么。Hooks 负责确保某些规则一定会执行。
比如你可以在提示词里写:
不要修改生产配置文件。
但这只是提醒 AI。
如果你通过 Hook 拦截application-prod.yml的编辑,那就不是提醒,而是门禁。
提示词是软约束。
Hooks 是硬约束。
两者应该配合使用。
对于低风险规则,可以写在提示词里。比如“保持代码风格一致”“参考已有测试写法”“不要过度重构”。
对于高风险规则,应该做成 Hook。比如“禁止危险命令”“禁止修改生产配置”“核心模块改动必须提示风险”。
这才是比较成熟的 AI Coding 使用方式。
不要把所有希望都寄托在提示词上。
真实工程里,规则要分层。
一个适合 Spring Boot 项目的 Hooks 目录结构
如果团队想认真使用 Claude Code,可以在项目里准备一个.claude目录。
比如:
.claude/settings.jsonhooks/block-dangerous-command.pyprotect-prod-config.pyjava-change-reminder.pymapper-change-reminder.pycore-module-reminder.py
其中settings.json负责配置什么时候触发哪些 Hook,hooks目录负责存放具体脚本。
这套东西不一定一开始就做得很复杂。可以先从最简单的三类门禁开始:
第一,危险命令拦截。
第二,生产配置保护。
第三,Java / Mapper 修改提醒。
这三类已经能解决很多真实问题。
等团队用得稳定以后,再逐步增加更细的规则,比如核心模块风险提示、自动格式化、测试命令建议、PR Review 检查等。
关键是不要一上来搞得太重。
AI 工程化最怕一开始就做成复杂系统,最后没人维护。
先从最常见、最确定、最危险的规则开始,效果会更好。
为什么这个方向比单纯写 AI 生成代码更重要?
因为 AI 生成代码已经不新鲜了。
现在读者看到“AI 帮我写了一个 Spring Boot 接口”,已经很难兴奋。大家更关心的是:这东西能不能真的放进团队流程里?能不能减少风险?能不能让真实项目更稳定?能不能避免 AI 改乱代码?
这就是 Hooks 这类能力的价值。
它代表 AI Coding 从“个人提效工具”开始走向“团队工程流程”。
个人使用 AI,可以靠经验和手动检查兜底。
团队使用 AI,就必须有规则、有门禁、有审计、有自动化。
否则每个人都用 AI 改代码,每个人的提示词不一样,每个人的检查习惯不一样,最后项目只会越来越不可控。
所以,真正成熟的 AI Coding,不是让 AI 写得越来越多,而是让 AI 在规则里写。
对 Java 团队来说,这一点尤其重要。
因为 Java 项目通常生命周期长、业务链路复杂、多人协作频繁、上线风险高。如果没有门禁,AI 的高效率反而可能放大风险。
未来 Java 团队可能会有一套 AI 开发门禁
我认为未来很多 Java 团队都会慢慢形成一套自己的 AI 开发门禁。
比如:
AI 不能修改生产配置。
AI 不能执行危险命令。
AI 不能直接改支付、订单、权限核心逻辑,必须先输出方案。
AI 修改 Java 文件后,必须说明测试建议。
AI 修改 Mapper XML 后,必须说明 SQL 风险。
AI 修改公共模块后,必须列出潜在影响范围。
AI 完成任务后,必须输出 diff 摘要和人工确认点。
这些规则一旦沉淀下来,AI 就不再只是一个“会写代码的助手”,而是被纳入团队工程流程里的协作者。
这也是 AI Coding 真正落地的关键。
如果没有门禁,AI 越强,团队越担心。
有了门禁,AI 越强,团队越敢用。
最后
过去我们讨论 AI Coding,最关注的是 AI 会不会写代码。
但到了真实 Java 项目里,问题已经变了。
现在真正重要的不是 AI 会不会写,而是 AI 能不能在规则里写。
能不能不碰生产配置。
能不能不执行危险命令。
能不能改完 Java 文件后提醒验证。
能不能改完 Mapper XML 后提醒 SQL 风险。
能不能涉及核心链路时主动输出影响范围。
这些事情,单靠提示词很难保证长期稳定。更可靠的方式,是把它们变成工具层的自动门禁。
Claude Code Hooks 这类机制的价值就在这里。
它让 AI Coding 不再只是“让模型自由发挥”,而是开始进入工程化管理。对于 Spring Boot 项目来说,这可能比让 AI 多写几个接口更重要。
因为真实项目最怕的,不是 AI 写得慢。
而是 AI 写得太快,却没人拦。
未来真正能把 AI 用好的 Java 团队,应该不是最早让 AI 写代码的团队,而是最早给 AI 建立工程门禁的团队。
今天就讲到这里,如果有问题需要咨询,大家可以直接留言或扫下方二维码来知识星球找我,我们会尽力为你解答。

快速搭建属于您的专属官网,就上TechWisdom(www.techwisdom.cn)!
提供100+ 精美模板,支持二级域名和独立域名配置,可根据需求进行个性化定制开发。首次上线还有专业团队协助上传内容,轻松打造高效、专业、吸睛的官网!立即访问网站,选择您心仪的模板,开启建站新体验吧!



作者:路条编程(转载请获本公众号授权,并注明作者与出处)
夜雨聆风