跳转到内容

SSM框架

💡

SSM = Spring + Spring MVC + MyBatis,是Java Web开发最经典的三大框架组合。Spring管理Bean和事务,SpringMVC处理Web层请求分发,MyBatis负责数据库持久层。三者整合形成完整的三层架构(表现层→业务层→持久层)。


一、Spring 核心

1.1 IoC(控制反转)与 DI(依赖注入)

📌

IoC(Inversion of Control):将对象的创建和依赖关系管理权从程序代码交给Spring容器,实现解耦。DI(Dependency Injection)是IoC的具体实现方式,容器在运行时将依赖注入到目标对象中。

依赖注入的三种方式

方式

实现

推荐度

构造器注入

@Autowired 或 @RequiredArgsConstructor + final字段

✅ 推荐(不可变、空指针安全)

Setter注入

@Autowired 标注setter方法

可选依赖时使用

字段注入

@Autowired 直接标注字段

❌ 不推荐(反射注入、难测试、隐藏依赖)

1.2 Spring Bean

Bean的作用域(Scope)

作用域

说明

singleton(默认)

整个IoC容器中只有一个实例(单例)。Spring容器启动时创建,线程不安全,字段不能存状态

prototype

每次getBean/createBean都创建新实例。容器不管理完整生命周期(初始化和销毁回调需自行调用)

request

每次HTTP请求创建新实例(Web应用)

session

每个HTTP Session一个实例(Web应用)

application

ServletContext生命周期内一个实例

Bean的生命周期

  1. 实例化:反射创建对象(推断构造器 → newInstance)
  2. 属性填充:依赖注入,填充@Autowired注解的属性
  3. Aware回调:调用BeanNameAware → BeanFactoryAware → ApplicationContextAware
  4. 前置处理:BeanPostProcessor.postProcessBeforeInitialization()(@PostConstruct在此之后调用)
  5. 初始化:@PostConstruct 或 InitializingBean.afterPropertiesSet() 或 @Bean(initMethod = "init")
  6. 后置处理:BeanPostProcessor.postProcessAfterInitialization()(AOP在此阶段生成代理对象)
  7. 就绪:Bean可用,被应用程序使用
  8. 销毁:@PreDestroy 或 DisposableBean.destroy() 或 @Bean(destroyMethod)

循环依赖:Spring通过三级缓存(singletonObjects→earlySingletonObjects→singletonFactories)解决构造器注入无法解决的循环依赖。只有单例且Setter注入的循环依赖可以解决,prototype和构造器注入的循环依赖抛BeanCurrentlyInCreationException。

1.3 AOP(面向切面编程)

📌

AOP通过动态代理在方法前后插入横切逻辑(日志、事务、权限、缓存),将核心业务与通用逻辑分离,消除重复代码。

核心概念

术语

说明

切面(Aspect)

横切逻辑的类,包含通知+切入点。@Aspect注解标记

连接点(JoinPoint)

程序执行过程中的点(方法调用、异常抛出)。Spring AOP仅支持方法级别的JoinPoint

切入点(Pointcut)

匹配连接点的表达式。execution(* com.example.service.*.*(..))匹配service包下所有方法

通知(Advice)

切面在特定连接点上执行的动作(Before/AfterReturning/AfterThrowing/After/Around)

织入(Weaving)

将切面应用到目标对象创建代理的过程。编译时(AspectJ)、类加载时、运行时(Spring AOP默认)

5种通知类型

通知

执行时机

@Before

目标方法执行前。不能阻止方法执行

@AfterReturning

目标方法正常返回后。可以获取返回值(returning属性)

@AfterThrowing

目标方法抛出异常后。可以获取异常信息(throwing属性)

@After(最终通知)

目标方法执行后(无论正常返回还是异常)。类似finally

@Around(环绕通知,最强)

包裹目标方法前后。通过ProceedingJoinPoint.proceed()控制方法执行。可修改参数、返回值、吞异常

Spring AOP底层原理:JDK动态代理 vs CGLIB

对比

JDK动态代理

CGLIB代理

要求

目标类必须实现接口

目标类不能被final修饰(通过继承创建子类)

实现

java.lang.reflect.Proxy + InvocationHandler

ASM字节码技术生成子类

Spring默认

Spring Boot 1.x默认JDK

Spring Boot 2.x起默认CGLIB(proxy-target-class=true)

性能

反射调用,微慢

直接调用,微快

局限性

只能代理接口方法

final类/方法不能代理;构造器被调用两次

1.4 Spring 事务管理

📌

声明式事务(@Transactional)基于AOP实现。方法开始→开启事务→执行业务逻辑→正常返回则提交→异常则按rollbackFor决定回滚或提交。

@Transactional核心属性

属性

说明

propagation

事务传播行为。REQUIRED(默认,加入或无则新建)、REQUIRES_NEW(挂起当前,新建事务)、NESTED(嵌套savepoint)、SUPPORTS/NOT_SUPPORTED/NEVER/MANDATORY

isolation

隔离级别。DEFAULT(数据库默认)、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE

rollbackFor

指定哪些异常回滚。默认只回滚RuntimeException和Error,受检异常不回滚(需显式指定)

timeout

事务超时时间(秒)。-1表示不限制

readOnly

只读事务(true时不允许修改,性能优化)。默认false

💡

事务失效的6种场景:(1) 类内部非事务方法调事务方法(自调用,this调用不经过代理) → 注入自身/AopContext.currentProxy() (2) 非public方法 → CGLIB不能代理 (3) 异常被catch吞掉 → 事务收不到异常 (4) rollbackFor指定错误 (5) 多线程(新线程不在事务内) (6) 数据库引擎不支持事务(MyISAM)。


二、Spring MVC

2.1 核心架构:DispatcherServlet

📌

Spring MVC基于前端控制器模式,DispatcherServlet作为唯一入口,统一接收所有请求并分发给对应的Controller处理。

请求处理全流程

  1. 请求到达:所有请求首先到达DispatcherServlet(前端控制器)
  2. 映射查找:DispatcherServlet调用HandlerMapping,根据URL找到对应的Controller和方法(Handler)
  3. 处理器适配:通过HandlerAdapter调用具体的Controller方法(适配不同类型的Handler)
  4. 业务处理:Controller调用Service层执行业务逻辑,返回ModelAndView(或@ResponseBody直接返回JSON)
  5. 视图解析:ViewResolver将逻辑视图名解析为实际View(JSP/Thymeleaf/FreeMarker)
  6. 渲染输出:View渲染模型数据,生成HTML/JSON响应返回客户端

2.2 核心组件

组件

作用

DispatcherServlet

前端控制器,所有HTTP请求的统一入口和调度中心

HandlerMapping

负责URL→Controller映射。RequestMappingHandlerMapping处理@Controller和@RequestMapping注解

HandlerAdapter

调用Handler(Controller方法),适配不同类型的处理器。RequestMappingHandlerAdapter处理注解方式

Handler(Controller)

具体的业务处理器,处理请求返回结果

ViewResolver

将逻辑视图名解析为实际View。InternalResourceViewResolver处理JSP,ThymeleafViewResolver处理Thymeleaf

HttpMessageConverter

HTTP请求/响应体的序列化/反序列化。@RequestBody/@ResponseBody用MappingJackson2HttpMessageConverter处理JSON

HandlerExceptionResolver

统一异常处理。@ExceptionHandler → @ControllerAdvice → 全局异常处理

Interceptor(拦截器)

请求前后拦截处理(日志、权限、跨域)。preHandle→postHandle→afterCompletion

2.3 核心注解

注解

作用

@Controller + @ResponseBody = @RestController

标记控制器类,所有方法返回JSON。@RestController = @Controller + @ResponseBody(Spring 4.0+)

@RequestMapping

URL映射(可指定method/params/headers/produces)。简化版:@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping

@RequestParam

获取URL参数 ?key=value。required=false时可选,defaultValue设置默认值

@PathVariable

获取路径变量 /user/{id}。与@RequestParam区分

@RequestBody

获取POST/PUT请求体的JSON,自动反序列化为Java对象

@RequestHeader

获取请求头信息。@RequestHeader("Authorization")

@CookieValue

获取Cookie值

@ModelAttribute

将请求参数绑定到对象(表单提交)

2.4 拦截器 vs 过滤器

对比

Filter(过滤器)

Interceptor(拦截器)

所属

Servlet规范,Tomcat容器管理

Spring MVC框架提供

执行顺序

先执行(在Servlet之前/之后)

后执行(在DispatcherServlet后,Controller前)

能否获取Bean

不能直接获取(是Servlet容器管理的)

可以(Spring管理的Bean可通过@Autowired注入)

适用场景

编码设置、XSS过滤、CORS、请求日志

登录校验、权限验证、日志AOP、性能监控

粒度

只能拿到request/response(没有请求方法信息)

能拿到Handler(Controller+方法),更精准控制


三、MyBatis

3.1 核心架构

📌

MyBatis是半自动ORM框架,开发者自己写SQL,框架负责SQL解析、参数映射、结果集映射。相比全自动ORM(Hibernate),MyBatis对SQL有完全控制力,适合复杂查询和性能优化场景。

3.2 核心组件

组件

作用

SqlSessionFactory

根据配置文件构建,线程安全,全局唯一。解析mybatis-config.xml和Mapper XML

SqlSession

一次数据库会话,非线程安全,用完即关。提供selectOne/selectList/insert/update/delete等方法

Executor

执行器,负责SQL执行、缓存维护、事务管理。SIMPLE(默认)/REUSE(缓存Statement)/BATCH(批处理)

MappedStatement

封装了SQL、参数映射、结果映射、缓存配置等元信息(每个<select>/<insert>/<update>/<delete>对应一个)

StatementHandler

处理JDBC Statement,设置参数、执行SQL、映射结果。含ParameterHandler和ResultSetHandler

TypeHandler

Java类型 ↔ JDBC类型转换。如java.util.Date ↔ java.sql.Timestamp

3.3 XML映射 vs 注解

#{} vs ${}:#{}是预编译占位符,安全防止SQL注入,自动加引号。${}是字符串拼接替换,有SQL注入风险,仅用于表名/列名等动态标识符。生产环境优先使用#{}。

3.4 动态SQL

标签

作用

<if test="条件">

条件判断,满足条件时拼入SQL片段。test中用OGNL表达式,and/or连接

<where>

包裹<if>等标签,自动处理WHERE关键字,去除开头的AND/OR

<choose>/<when>/<otherwise>

类似switch-case-default,多选一

<foreach>

遍历集合。collection=list/array/@Param名;item=元素;open/close=首尾字符;separator=分隔符

<set>

动态UPDATE,自动处理SET关键字,去除末尾逗号

<trim>

更灵活的字符串截取。prefix/suffix(前缀/后缀)、prefixOverrides/suffixOverrides(去除首/尾指定字符)

<sql> + <include>

SQL片段复用。<sql id="cols">id,name,email</sql> → <include refid="cols"/>

3.5 缓存机制

一级缓存(SqlSession级别,默认开启)

  • 作用范围:同一个SqlSession内,同样的查询只执行一次SQL,后续从缓存取
  • 失效条件:执行增删改操作(commit)、手动清缓存(clearCache())、不同SqlSession

二级缓存(Mapper级别,默认关闭)

  • 作用范围:同一个namespace(Mapper接口)下,不同SqlSession共享
  • 启用:mybatis-config.xml中 setting cacheEnabled=true + Mapper XML中加<cache/>
  • 要求:实体类必须实现Serializable(因为需要序列化存储)
  • 命中顺序:二级缓存 → 一级缓存 → 数据库
  • 注意:在生产环境不推荐使用,用Redis等分布式缓存替代(跨实例一致性)

3.6 MyBatis工作流程

  1. 加载mybatis-config.xml和Mapper XML → 解析为Configuration对象 → 构建SqlSessionFactory
  2. SqlSessionFactory.openSession()创建SqlSession(同时创建Executor和Transaction)
  3. getMapper(UserMapper.class) → JDK动态代理生成Mapper代理对象
  4. 调用mapper.selectById(1) → 代理拦截 → 根据全限定名+方法名查找MappedStatement
  5. Executor执行:查二级缓存 → 查一级缓存 → 执行SQL → StatementHandler设置参数 → JDBC执行
  6. ResultSetHandler将ResultSet映射为Java对象(通过ResultMap或自动映射)
  7. 返回结果 → 放入一级缓存 → 关闭SqlSession

3.7 MyBatis-Plus

💡

MyBatis-Plus是MyBatis的增强工具,在MyBatis基础上只做增强不做改变。提供通用CRUD(BaseMapper)、条件构造器(Wrappers)、分页插件(PaginationInnerInterceptor)、自动填充等开箱即用功能。

特性

使用方式

通用CRUD

extends BaseMapper<User>,无需写SQL即可获得insert/deleteById/updateById/selectById/selectList

条件构造器

Wrappers.<User>lambdaQuery().eq(User::getName, "张三").gt(User::getAge, 18)

分页插件

Page<User>.of(pageNum, pageSize) → selectPage → 自动分页COUNT+LIMIT

逻辑删除

@TableLogic,delete自动转为UPDATE SET deleted=1(逻辑删除而非物理删除)

自动填充

@TableField(fill = FieldFill.INSERT),配合MetaObjectHandler自动填充createTime/updateTime

乐观锁

@Version 注解 + version字段,update时自动WHERE version = #{et.version} AND SET version = version + 1


四、SSM整合

4.1 三层架构

📌

表现层(Controller):SpringMVC接收HTTP请求,参数校验,调用Service → 业务层(Service):Spring管理事务(@Transactional),编排业务逻辑 → 持久层(Dao/Mapper):MyBatis执行SQL操作数据库。

4.2 典型配置

4.3 Spring Boot整合要点

功能

核心注解/配置

Spring容器

@SpringBootApplication(包含@Configuration + @EnableAutoConfiguration + @ComponentScan)

SpringMVC

自动配置,spring-boot-starter-web依赖。@RestController处理请求

MyBatis

mybatis-spring-boot-starter。@MapperScan("com.example.mapper") 扫描Mapper接口

事务

spring-boot-starter-jdbc / aop,@EnableTransactionManagement + @Transactional

数据源

application.yml 配置 spring.datasource.url/username/password/driver-class-name。默认HikariCP连接池


面试高频梳理:

  • Spring必问:IoC/DI概念、Bean生命周期、AOP原理(JDK/CGLIB)、@Transactional事务失效场景、循环依赖
  • SpringMVC必问:DispatcherServlet处理流程、Filter vs Interceptor、@RestController注解组合
  • MyBatis必问:#{}和${}区别、一级/二级缓存、动态SQL、工作流程
  • 整合:三层架构职责划分、Spring Boot自动配置原理