卓望(中国移动)后端 AI 面:深浅拷贝、循环依赖与 MCP
- 轮次
- AI 面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 深拷贝和浅拷贝有什么区别?
Object.assign之后修改对象的属性,原对象的属性会变化吗? - Spring 循环依赖问题,哪些场景不能解决?
- MCP 解决了什么?MCP 返回的工具描述与大模型的调用格式不兼容怎么办?
- MySQL 主从延迟的原因有哪些?
- XSS 是什么?分为哪几种?
- Agent 的长期记忆该保存哪些内容?如何记忆冲突怎么办?
- 用户的临时偏好会保存吗?例如「今天我喜欢喝冰美式」。
- 如何实时读取 Linux 中的日志文件内容?
《参考解析》
深浅拷贝与 Object.assign。 浅拷贝只复制第一层属性的值:基本类型复制值,引用类型复制地址,所以新旧对象共享同一个嵌套对象。Object.assign({}, obj) 就是浅拷贝:改顶层基本类型属性不会影响原对象(因为是值复制),但改嵌套对象(obj.a.b = 1)会影响原对象,因为 a 指向同一个对象。深拷贝会递归复制所有层级,常用 structuredClone(现代浏览器/Node 17+,支持 Date/Map/Set,但不能克隆函数)、递归实现(要处理循环引用、Date、RegExp、Map/Set)、或库(lodash cloneDeep)。JSON.parse(JSON.stringify(obj)) 是老办法,但会丢函数/undefined/Symbol、把 Date 变字符串、且不能处理循环引用。回答时要点出「不可变数据」的实践:需要修改嵌套状态时用展开运算符逐层复制,或者用 Immer,避免副作用。
Spring 循环依赖哪些场景解决不了。 Spring 用三级缓存解决「单例 Bean 的字段注入/Setter 注入」循环依赖:一级存成品 Bean,二级存早期暴露的对象,三级存 ObjectFactory(用于生成 AOP 代理)。解决不了的情况:构造器注入的循环依赖(对象还没创建完就需要另一个对象,无法提前暴露);原型(prototype)作用域的循环依赖(不做缓存);@Async/AOP 代理与循环依赖叠加时的特殊场景(早期引用与最终代理不一致,可能注入到原始对象);以及 @Deprecated 的 allowCircularReferences=false(Spring Boot 2.6+ 默认禁止循环依赖,会直接报错)。正确做法不是「想办法绕过」,而是重构:把循环依赖抽成第三个 Bean、用事件解耦、用 @Lazy 延迟注入、或调整职责边界。答题时能说出「三级缓存各存什么、为什么需要三级而不是两级」是加分项。
MCP 与工具描述不兼容。 MCP(Model Context Protocol)解决的是「模型/客户端如何标准化地发现和调用外部工具与数据源」:把工具、资源、提示词抽象成统一协议,客户端连上 MCP Server 就能拿到工具列表并调用,不用为每个模型/框架单独写适配。它和 Function Calling 的区别是:Function Calling 是模型厂商的调用格式,MCP 是跨厂商的工具接入协议(可以理解为「工具侧的 USB-C」)。工具描述与模型调用格式不兼容,通常是这几类问题:JSON Schema 方言不一致(如 anyOf/$ref 模型不支持)、描述过长被截断、参数类型不匹配(字符串 vs 对象)、必填项缺失、或工具名冲突。解决思路是加一层适配:在 MCP Server 侧把 Schema 降级成模型支持的子集(扁平化、去掉复杂组合、补默认值)、把工具描述压缩成「一句话用途 + 关键参数」、对参数做服务端校验与纠错、以及把调用失败的错误信息结构化返回给模型让它重试。工程上还要做工具白名单、超时、重试、以及调用日志。
MySQL 主从延迟的原因。 先分清是「主库写入太快」还是「从库回放太慢」。常见原因:从库单线程回放(老版本)或并行复制配置不足,主库高并发写入时从库跟不上;大事务(批量 delete/update、大表 DDL)导致从库长时间回放一个事务;从库硬件差(磁盘 IOPS、CPU)、或从库还承担大量读请求;无主键表导致 row 格式下每次更新全表扫描;锁冲突(从库上有长查询/备份阻塞回放);网络延迟或半同步复制等待;以及主库 binlog 刷盘策略与从库 sync_binlog/innodb_flush_log_at_trx_commit 配置不同。排查手段:SHOW SLAVE STATUS 看 Seconds_Behind_Master(不准,只作参考)、对比主从 binlog 位点、看 performance_schema 的复制线程状态、以及用 pt-heartbeat 测真实延迟。解决:开并行复制(slave_parallel_workers + LOGICAL_CLOCK)、拆大事务、加主键、从库扩容/分离读流量、以及业务侧「写后读」走主库或用缓存兜底。
XSS 的分类与防御。 XSS 是攻击者把脚本注入页面,在其他用户浏览器里执行。三类:存储型(恶意内容存进数据库,所有访问者中招,危害最大)、反射型(恶意内容在 URL/表单里,服务端原样返回,诱导受害者点击)、DOM 型(前端 JS 直接把不可信数据写入 innerHTML/document.write/eval,不经过服务端)。防御的核心是「按输出上下文编码」:HTML 内容用 HTML 实体编码,属性用属性编码,JS 用 JS 编码,URL 用 URL 编码;不要用黑名单过滤 <script>(绕过方式太多)。再配合:CSP(限制脚本来源、禁用 inline script)、HttpOnly Cookie(防会话窃取)、输入校验(白名单)、以及富文本用成熟的 sanitizer(DOMPurify)。React/Vue 默认转义,但 dangerouslySetInnerHTML/v-html 会绕过,要特别注意。
Agent 长期记忆与临时偏好。 长期记忆应该存「稳定、可复用、对后续决策有影响」的信息:用户身份与长期偏好(语言、职业、习惯)、重要事实与事件(项目、目标、关键日期)、关系(同事/家人)、以及历史决策与反馈(喜欢什么、拒绝过什么)。不该存:一次性上下文、敏感信息(除非明确授权并加密)、以及可从原始数据推导的冗余内容。记忆冲突的处理:给每条记忆加来源、时间、置信度;冲突时按「用户显式确认 > 新近 > 高频 > 置信度」排序,保留冲突记录而不是直接覆盖;定期做记忆整理(合并重复、淘汰过期、让用户可查看/编辑/删除)。临时偏好(「今天想喝冰美式」)应该存短期记忆/会话状态,带 TTL,不写入长期画像;如果同一偏好反复出现(连续一周),再提升为长期偏好。关键是区分「事实」「偏好」「临时状态」,并让用户对记忆有控制权。