1. 面试场景还原:从Spring Boot到Kafka的三轮技术攻防战
去年冬天的一次技术面试让我印象深刻。候选人谢飞机(化名)简历上写着"精通Spring全家桶、消息中间件和ORM框架",但实际交流中暴露的问题却成了绝佳的教学案例。这场持续90分钟的技术问答,完美呈现了Java工程师在面试中最容易踩中的技术雷区。
第一轮围绕Spring Boot展开,当被问到自动配置原理时,谢同学的回答停留在"@EnableAutoConfiguration会加载META-INF/spring.factories"的层面。这就像说汽车会跑是因为有轮子——完全没触及Spring Boot最核心的条件装配(Conditional)机制。更致命的是,他把Spring Boot Starter的作用说成了"简化依赖下载",完全忽略了Starter最关键的"约定优于配置"设计哲学。
第二轮MyBatis环节出现了典型的安全误区。谈到动态SQL时,他自信地表示"#{}和${}可以混用,只要做好参数校验"。但当被要求解释奇安信扫描报SQL注入漏洞的场景时,却说不清预编译语句(PreparedStatement)与字符串拼接的本质区别。最戏剧性的是第三轮Kafka部分,当讨论到SASL认证配置时,他竟把ACL权限列表和SASL机制混为一谈,这相当于把门禁卡和指纹锁当成了同一种东西。
2. Spring Boot深度拷问:自动配置的七个认知层级
2.1 从表面到本质的认知跃迁
大多数候选人对Spring Boot自动配置的理解停留在Level 1~3:
- Level 1:知道加@SpringBootApplication注解就能启动
- Level 2:了解spring.factories文件的作用
- Level 3:会说"按需加载"这样的套话
而高级工程师应该达到Level 5以上:
- Level 4:能解释@Conditional系列注解的工作机制
- Level 5:理解AutoConfigurationImportSelector的筛选逻辑
- Level 6:掌握spring-autoconfigure-metadata.properties的过滤规则
- Level 7:能自定义Starter并实现智能装配
面试中一个经典的深度问题是:"如果同时存在HikariCP和Druid数据源,Spring Boot如何决定使用哪个?"正确答案应该涉及:
- DataSourceAutoConfiguration的加载顺序
- @ConditionalOnClass的条件判断
- spring.datasource.type的显式指定优先级
2.2 Starter设计思想的本质理解
谢同学对spring-boot-starter-web的认知偏差很有代表性。真正的Starter设计包含三个维度:
- 依赖管理(Dependency Management)
- 不是简单的jar包集合,而是经过严格测试的版本组合
- 通过BOM(Bill of Materials)确保组件兼容性
- 自动配置(Auto-configuration)
- 基于类路径检测的智能默认配置
- 提供合理的override机制
- 可观测性(Observability)
- 内置健康检查端点
- 提供标准化指标输出
避坑指南:面试时若被问到Starter原理,切忌只说"方便导包"。应该从"约定优于配置"的角度,结合具体Starter的实现展开说明。
3. MyBatis安全防线:从SQL注入到动态SQL最佳实践
3.1 ${}的致命诱惑与防御之道
谢同学在MyBatis动态SQL上的错误认知极具警示意义。以下是关键对比:
| 特性 | #{} (预编译) | ${} (字符串拼接) |
|---|---|---|
| 安全等级 | 可防御SQL注入 | 存在注入风险 |
| 执行方式 | PreparedStatement | Statement |
| 参数处理 | 类型安全转换 | 直接替换 |
| 适用场景 | 值传递 | 表名/列名等元数据 |
即使必须使用${}的场景(如动态表名),也应该:
- 在Mapper接口方法上添加@Param注解明确参数用途
- 在XML中使用
标签预处理参数 - 添加正则表达式校验(如:
<if test="tableName =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/">)
3.2 动态SQL的进阶用法
面试中常被低估的MyBatis动态SQL能力包括:
- 脚本动态化:在
