面灵AI→

卓望(中国移动)后端 AI 面:深浅拷贝、循环依赖与 MCP

轮次
AI 面
时间
2026-10
来源
牛客网

《面试题目》

  1. 深拷贝和浅拷贝有什么区别?Object.assign 之后修改对象的属性,原对象的属性会变化吗?
  2. Spring 循环依赖问题,哪些场景不能解决?
  3. MCP 解决了什么?MCP 返回的工具描述与大模型的调用格式不兼容怎么办?
  4. MySQL 主从延迟的原因有哪些?
  5. XSS 是什么?分为哪几种?
  6. Agent 的长期记忆该保存哪些内容?如何记忆冲突怎么办?
  7. 用户的临时偏好会保存吗?例如「今天我喜欢喝冰美式」。
  8. 如何实时读取 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,不写入长期画像;如果同一偏好反复出现(连续一周),再提升为长期偏好。关键是区分「事实」「偏好」「临时状态」,并让用户对记忆有控制权。