
1. SSM框架的核心定位与技术栈组成SSMSpringSpringMVCMyBatis作为Java企业级开发的经典组合其技术栈构成远比表面看到的三个字母复杂。Spring框架最初是作为轻量级容器出现的但发展到今天已经成为事实上的Java企业开发标准。Spring 5.x版本引入的反应式编程模型虽然拓展了能力边界但在传统Web开发领域基于IoC和AOP的核心机制仍是面试考察重点。SpringMVC的DispatcherServlet工作原理常被简化为前端控制器模式但实际上其内部HandlerMapping的匹配策略、HandlerAdapter的适配逻辑、ViewResolver的解析流程都值得深挖。特别是在RESTful接口设计中从HTTP请求到Controller方法的参数绑定过程涉及到的Converter和Formatter体系往往是被忽视的深度考点。MyBatis的SQL映射机制看似简单但其动态SQL生成、二级缓存实现、插件拦截器体系等特性在应对复杂业务场景时展现出极强的灵活性。与Hibernate这类全自动ORM相比MyBatis的半自动化特性使其在大数据量操作和复杂SQL优化场景中更具优势这也是面试官喜欢追问MyBatis原理的重要原因。2. Spring IoC容器的实现机理与高频考点2.1 Bean生命周期管理的完整链路从XML配置或注解声明开始一个Bean要经历实例化、属性填充、初始化、销毁等多个阶段。Spring通过BeanDefinition对象封装配置元数据这个过程中BeanFactoryPostProcessor和BeanPostProcessor的扩展点尤为重要。常见的面试陷阱包括循环依赖的解决机制三级缓存Autowired与Resource的注入差异配置类Bean方法与Component注解的初始化顺序差异2.2 AOP代理的底层实现方案Spring AOP默认使用JDK动态代理基于接口和CGLIB字节码增强基于类继承两种方式。面试中常要求手写简单AOP实现此时需要明确// 简化的代理工厂示例 public class ProxyFactory { public static Object createProxy(Object target, Advice advice) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) - { advice.before(); Object result method.invoke(target, args); advice.after(); return result; } ); } }实际Spring的实现要考虑代理链、异常处理等复杂情况但核心原理与此类似。需要特别注意Transactional等注解的代理生效条件。3. SpringMVC请求处理的全流程解析3.1 九大核心组件的协作流程一次HTTP请求在SpringMVC中的处理路径可以分解为DispatcherServlet接收请求HandlerMapping确定处理程序HandlerAdapter执行实际方法参数解析与数据绑定拦截器预处理控制器方法执行返回值处理视图渲染拦截器后处理其中最容易出问题的环节是参数绑定阶段。比如RequestBody处理JSON输入时需要明确MessageConverter的选择逻辑日期格式等特殊类型的处理验证注解(Valid)的执行时机3.2 RESTful接口设计的实践要点现代接口设计往往要求符合HATEOAS规范此时需要注意GetMapping(/users/{id}) public ResourceUser getUser(PathVariable Long id) { User user userService.findById(id); ResourceUser resource new Resource(user); resource.add(linkTo(methodOn(UserController.class).getUser(id)).withSelfRel()); return resource; }这种设计方式虽然优雅但在实际面试中更常考察的是PathVariable与RequestParam的区别统一异常处理(ControllerAdvice)跨域解决方案(CORS配置)4. MyBatis的进阶特性与优化策略4.1 动态SQL的工程化实践MyBatis提供了强大的动态SQL能力但复杂查询的维护是个挑战select idfindUsers resultTypeUser SELECT * FROM users where if testname ! null AND name LIKE #{name} /if choose when testrole admin AND level 10 /when otherwise AND status 1 /otherwise /choose /where /select面试中可能会要求对比MyBatis与JPA的Criteria查询此时要强调MyBatis在复杂查询性能上的优势。4.2 缓存机制与事务管理MyBatis的一级缓存(SqlSession级别)和二级缓存(Mapper级别)是常考重点。特别要注意二级缓存导致脏读的场景本地缓存与Redis等分布式缓存的整合事务传播行为与Spring事务的协同在整合Spring事务时常见配置陷阱包括!-- 错误示例两个事务管理器冲突 -- bean idtxManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource/ /bean tx:annotation-driven transaction-managertxManager/ bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ property nametransactionFactory bean classorg.apache.ibatis.transaction.managed.ManagedTransactionFactory/ /property /bean正确的做法是使用SpringManagedTransactionFactory。5. 性能优化与生产实践5.1 连接池配置要点以HikariCP为例关键参数包括spring.datasource.hikari.maximum-pool-size20 spring.datasource.hikari.minimum-idle5 spring.datasource.hikari.idle-timeout30000 spring.datasource.hikari.max-lifetime1800000 spring.datasource.hikari.connection-timeout30000这些参数的设置需要根据实际QPS和SQL执行时间进行调整。常见误区是盲目增大连接数实际上连接池大小应该符合公式connections (core_count * 2) effective_spindle_count5.2 SQL性能优化实战MyBatis的SQL优化需要结合执行计划分析。典型优化手段包括避免SELECT * 写法合理使用索引提示批量操作代替循环单条处理// 低效写法 for (User user : userList) { userMapper.insert(user); } // 高效写法 insert idbatchInsert parameterTypelist INSERT INTO users(name,age) VALUES foreach collectionlist itemitem separator, (#{item.name},#{item.age}) /foreach /insert6. 常见面试题深度剖析6.1 Spring循环依赖的解决机制三级缓存的工作流程singletonObjects完整BeanearlySingletonObjects早期引用singletonFactoriesObjectFactory解决过程示例// 伪代码展示解决过程 class DefaultSingletonBeanRegistry { protected Object getSingleton(String beanName) { Object singleton singletonObjects.get(beanName); if (singleton null isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singleton earlySingletonObjects.get(beanName); if (singleton null) { ObjectFactory? singletonFactory singletonFactories.get(beanName); if (singletonFactory ! null) { singleton singletonFactory.getObject(); earlySingletonObjects.put(beanName, singleton); singletonFactories.remove(beanName); } } } } return singleton; } }6.2 MyBatis插件开发实战实现分页插件的核心步骤Intercepts(Signature(typeStatementHandler.class, methodprepare, args{Connection.class,Integer.class})) public class PaginationInterceptor implements Interceptor { Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler handler (StatementHandler) invocation.getTarget(); BoundSql boundSql handler.getBoundSql(); String sql boundSql.getSql(); // 修改SQL添加LIMIT String newSql sql LIMIT ?,?; Field field boundSql.getClass().getDeclaredField(sql); field.setAccessible(true); field.set(boundSql, newSql); // 设置参数 ParameterHandler parameterHandler handler.getParameterHandler(); parameterHandler.setParameters(/* 分页参数 */); return invocation.proceed(); } }7. 框架整合中的典型问题7.1 事务失效的常见场景方法非public修饰同类方法自调用异常类型不匹配数据库引擎不支持传播行为配置错误验证事务是否生效的测试方法Transactional public void transfer(Long from, Long to, BigDecimal amount) { accountMapper.debit(from, amount); int i 1/0; // 故意制造异常 accountMapper.credit(to, amount); }7.2 多数据源配置陷阱典型的多数据源配置需要Configuration MapperScan(basePackages com.dao.db1, sqlSessionFactoryRef db1SqlSessionFactory) public class Db1Config { Bean ConfigurationProperties(spring.datasource.db1) public DataSource db1DataSource() { return DataSourceBuilder.create().build(); } Bean public SqlSessionFactory db1SqlSessionFactory(Qualifier(db1DataSource) DataSource dataSource) throws Exception { SqlSessionFactoryBean bean new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/db1/*.xml)); return bean.getObject(); } Bean public DataSourceTransactionManager db1TransactionManager( Qualifier(db1DataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }关键是要确保事务管理器、SqlSessionFactory、Mapper扫描路径的对应关系正确。