面试八股文专题----SSM框架篇

简介: 本篇深入解析SSM框架核心:Spring的IOC/DI、AOP、事务管理及传播行为,详解JDK/CGLIB代理差异;SpringMVC请求流程与常用注解;Mybatis动态SQL、多表查询、缓存机制及批量操作,全面掌握企业级开发关键技术要点。

2-SSM框架篇

01-什么是Spring IOC 和DI ?

IOC(控制反转):把传统上由程序代码直接操控的对象调用权交给容器,通过容器实现对象组件的装配和管理。“控制反转”的核心是组件对象控制权的转移,从程序代码本身转移到外部容器,不再由开发者手动创建和管理对象,而是由Spring容器统一管控。
DI(依赖注入):是IOC的具体实现方式,在创建对象的过程中,将对象所依赖的属性(比如其他类的实例)自动注入到该类中,无需开发者手动设置依赖,以此实现对象间依赖关系的解耦。

02-有哪些不同类型的依赖注入实现方式?

依赖注入主要有三种实现方式:

  1. 接口注入:通过特定接口暴露依赖注入的入口,容器借助该接口将依赖注入到目标对象中(实际开发中极少使用);
  2. 构造器依赖注入:容器通过触发类的构造器完成注入,该类的构造器包含一系列参数,每个参数对应对其他类的依赖,容器会在创建对象时传入这些依赖对象;
  3. Setter方法注入:容器先通过无参构造器或无参static工厂方法实例化Bean,再调用该Bean的Setter方法,将依赖对象注入,是实际开发中最常用的注入方式。

03- Spring支持的几种bean的作用域 Scope

Spring框架支持五种Bean作用域:

  1. singleton(单例):每个Spring IOC容器中,该Bean仅存在一个实例,是Spring Bean的默认作用域;
  2. prototype(原型):一个Bean定义可以创建多个实例,每次从容器中获取该Bean时都会生成新的实例;
  3. request(请求):每次HTTP请求都会创建一个新的Bean实例,该作用域仅在基于Web的Spring ApplicationContext环境下有效;
  4. session(会话):在一个HTTP Session生命周期内,一个Bean定义对应一个实例,仅在基于Web的Spring ApplicationContext环境下有效;
  5. global-session(全局会话):在全局HTTP Session中,一个Bean定义对应一个实例,主要用于Portlet环境,仅在基于Web的Spring ApplicationContext环境下有效。

04- Spring框架中的单例bean是线程安全的吗?

Spring框架中的单例Bean本身不是线程安全的。因为Spring默认的Bean是单例模式,Spring框架并未对单例Bean做多线程相关的封装或同步处理。
但实际开发中,若单例Bean中不包含共享的成员变量(比如全局的状态数据),仅作为无状态的工具类/服务类使用,就不会出现线程安全问题;从这个角度来说,日常使用的单例Bean通常是“线程安全”的。

05- spring 自动装配 bean 有哪些方式?

在Spring框架的XML配置中,主要有3种核心自动装配方式:

  1. byName(按名称装配):根据Bean的名称进行自动装配,如果一个Bean的属性名与另一个Bean的name属性值相同,Spring容器会自动将后者注入到前者的该属性中;
  2. byType(按类型装配):根据参数的数据类型进行自动装配,如果容器中存在唯一匹配该属性类型的Bean,就将其注入;若存在多个同类型Bean,会抛出异常;
  3. constructor(构造器装配):利用构造函数完成装配,构造函数的参数会通过byType方式匹配容器中的Bean,再注入到构造器中创建对象。

06- Spring中的事务是如何实现的

Spring事务底层基于数据库事务和AOP(面向切面编程)机制实现,核心流程如下:

  1. 对于标注了@Transactional注解的Bean,Spring会为其创建代理对象;
  2. 调用代理对象的方法时,先判断方法上是否有@Transactional注解;
  3. 若有注解,通过事务管理器创建数据库连接,并将该连接的autocommit(自动提交)属性设为false(这是Spring事务实现的关键步骤);
  4. 执行当前方法中的SQL逻辑;
  5. 方法执行完成后,若无异常则提交事务;若出现异常,且该异常属于需要回滚的类型(默认是RuntimeException及其子类),则回滚事务,否则仍提交事务;
  6. Spring事务的隔离级别直接对应数据库的隔离级别;事务的传播机制是Spring自身实现的核心特性,基于数据库连接实现:一个数据库连接对应一个事务,若传播机制要求新开事务,本质是新建一个数据库连接并在该连接上执行SQL。

07- Spring中事务失效的场景

Spring事务基于动态代理实现,以下场景会导致@Transactional注解失效:

  1. 非代理对象调用:加了@Transactional的方法被Bean自身(而非代理对象)调用(比如内部方法调用),注解无法被Spring的AOP拦截,导致失效;
  2. 方法为private修饰:底层CGLIB动态代理基于父子类实现,子类无法重载父类的private方法,代理无法生效,@Transactional失效;
  3. 异常被手动捕获:业务代码中捕获了异常且未重新抛出,Spring框架无法感知异常,无法触发事务回滚,导致事务失效;
  4. 注解标注在非public方法上:Spring AOP仅对public方法的@Transactional做代理处理,非public方法注解无效。

08- 说一下Spring的事务传播行为

Spring事务传播行为定义了多个带有事务的方法相互调用时,事务的创建、加入或挂起规则,核心传播行为如下:

  1. PROPAGATION_REQUIRED(默认):如果当前无事务,创建新事务;如果当前已有事务,加入该事务,是最常用的设置;
  2. PROPAGATION_SUPPORTS:支持当前事务,若当前有事务则加入,若无则以非事务方式执行;
  3. PROPAGATION_MANDATORY:强制要求当前存在事务,若有则加入,若无则抛出异常;
  4. PROPAGATION_REQUIRES_NEW:无论当前是否有事务,都创建新事务(原有事务会被挂起,新事务执行完后恢复原有事务);
  5. PROPAGATION_NOT_SUPPORTED:以非事务方式执行,若当前有事务则将其挂起;
  6. PROPAGATION_NEVER:以非事务方式执行,若当前存在事务则抛出异常;
  7. PROPAGATION_NESTED:若当前有事务,在嵌套事务内执行(嵌套事务依赖外层事务,外层回滚则嵌套也回滚,嵌套回滚不影响外层);若当前无事务,按PROPAGATION_REQUIRED规则执行。

09- JDK动态代理和CGLIB动态代理的区别

Spring AOP的动态代理主要有JDK动态代理和CGLIB动态代理两种方式,核心区别如下:

  1. 实现原理:JDK动态代理基于接口实现,通过Proxy.newProxyInstance(类加载器, 代理对象实现的所有接口, 代理执行器)创建代理对象,仅支持对接口的代理;CGLIB动态代理基于继承实现,通过Enhancer.create(父类的字节码对象, 代理执行器)创建代理对象,代理类是目标类的子类;
  2. 适用范围:JDK动态代理要求目标类必须实现接口,否则无法代理;CGLIB无需目标类实现接口,但目标类若被标记为final(无法被继承),则无法使用CGLIB代理;
  3. 性能:JDK1.8后JDK动态代理性能优于CGLIB,低版本JDK中CGLIB性能更优。

10- 什么是AOP , 你们项目中有没有使用到AOP

AOP(面向切面编程):作为面向对象编程(OOP)的补充,将与业务无关但对多个对象产生影响的公共行为和逻辑(比如日志、权限、事务)抽取封装为可重用的“切面(Aspect)”,减少系统重复代码,降低模块耦合度,提升可维护性。
项目中直接手写AOP的场景较少,但大量框架功能底层基于AOP实现:比如Spring的事务管理(@Transactional)、权限认证(比如拦截请求校验权限)、系统日志记录(统一记录接口入参出参)、异常统一处理等,都是AOP的典型应用。

11- SpringMVC的执行流程知道嘛

SpringMVC的核心执行流程如下:

  1. 用户发送HTTP请求至前端控制器DispatcherServlet;
  2. DispatcherServlet调用HandlerMapping(处理器映射器),根据请求URL查找对应的Handler(处理器,即Controller中的方法);
  3. HandlerMapping返回处理器对象及对应的处理器拦截器(若有)给DispatcherServlet;
  4. DispatcherServlet调用HandlerAdapter(处理器适配器),适配并执行对应的Handler;
  5. HandlerAdapter适配后调用具体的Handler(后端控制器),Handler执行完成后返回ModelAndView(模型数据+视图名称);
  6. HandlerAdapter将ModelAndView返回给DispatcherServlet;
  7. DispatcherServlet将ModelAndView传给ViewResolver(视图解析器),视图解析器解析出具体的View(视图);
  8. DispatcherServlet对View进行渲染(将Model中的数据填充到视图中);
  9. DispatcherServlet将渲染后的视图响应给用户。

12- Spring MVC常用的注解有哪些?

Spring MVC常用注解及作用:

  1. @RequestMapping:处理请求URL映射,可标注在类或方法上;标注在类上时,类中所有响应请求的方法都以该地址为父路径;
  2. @RequestBody:接收HTTP请求中的JSON数据,自动将JSON转换为Java对象;
  3. @ResponseBody:将Controller方法的返回对象转换为JSON对象,响应给客户端;
  4. @Controller:标注类为Spring MVC的控制器(表现层),是核心注解,无法被其他注解替代;
  5. @RestController:组合注解,等价于@Controller + @ResponseBody,标注后方法返回值直接以JSON响应,无需额外加@ResponseBody;
  6. @GetMapping/@PostMapping/@PutMapping/@DeleteMapping:分别对应GET/POST/PUT/DELETE请求的映射注解,是@RequestMapping的简化版;
  7. @PathVariable:接收请求路径中的路径变量(比如/{id}中的id);
  8. @RequestParam:接收请求参数(比如URL中的?id=123或表单参数),可指定参数名、是否必传、默认值等。

13- Mybatis #{}和${}的区别

Mybatis中#{}和${}是两种参数绑定方式,核心区别如下:

  1. 处理方式:#{}是占位符,做预编译处理;Mybatis会将SQL中的#{}替换为?,调用PreparedStatement的set方法赋值,参数以字符串形式传入;${}是字符串拼接符,做字符串替换,无预编译处理,直接将参数拼接到SQL中;
  2. 安全性:#{}能有效防止SQL注入(因为预编译处理,参数被当作值而非SQL语句),提升系统安全性;${}无法防止SQL注入,参数直接拼接可能被恶意注入;
  3. 替换位置:#{}的变量替换在数据库系统内部完成;${}的变量替换在数据库系统外(Mybatis框架层面)完成。

14- Mybatis 如何获取生成的主键

Mybatis获取插入操作生成的主键主要有两种方式:

  1. 基于insert标签属性:在insert标签上添加useGeneratedKeys="true"(开启获取自增主键),同时设置keyProperty="主键字段名"(比如userId),插入后主键值会自动填充到实体类的对应属性中;
  2. 基于selectKey标签:在insert标签内部添加selectKey标签,通过执行SQL(比如MySQL的select last_insert_id())查询生成的主键,并将结果赋值给实体类的主键属性。

15- 当实体类中的属性名和表中的字段名不一样 ,怎么办

解决实体类属性名与数据库表字段名不一致的问题,主要有两种方式:

  1. SQL别名方式:在查询SQL中为字段名定义别名,使别名与实体类的属性名一致(比如SELECT user_name AS userName FROM user);
  2. ResultMap映射方式:在Mybatis的映射文件中定义ResultMap,明确指定数据库字段名与实体类属性名的映射关系,是更通用、可复用的方式。

16- Mybatis如何实现多表查询

Mybatis实现多表查询主要有两种方式:

  1. 关联查询方式:编写多表关联的SQL语句(比如JOIN),通过ResultMap建立结果集映射,使用association标签(一对一关联)、collection标签(一对多关联)映射关联对象/集合;
  2. 分步查询方式:将多表查询拆分为多个单表查询,在ResultMap的association/collection标签中通过select属性指定另一个SQL的ID,Mybatis会自动执行该SQL并将结果封装到关联对象/集合中。

17-Mybatis都有哪些动态sql?能简述一下动态sql的执行原理吗?

Mybatis动态SQL允许在XML映射文件中通过标签编写动态逻辑,完成SQL的条件拼接,核心动态SQL标签包括:trim、where、set、foreach、if、choose、when、otherwise、bind共9种。
动态SQL的执行原理:Mybatis通过OGNL(对象图导航语言)从SQL参数对象中计算表达式的值,根据表达式的结果动态拼接SQL语句,最终生成可执行的SQL并执行,以此实现SQL的动态调整。

18- Mybatis是否支持延迟加载?

Mybatis支持延迟加载(懒加载),但仅支持association(一对一关联)和collection(一对多关联)对象的延迟加载:

  1. 延迟加载的核心逻辑:查询主表数据时,不立即查询关联表数据,仅在首次访问关联对象/集合时,才执行关联查询;
  2. 开启方式:在Mybatis的核心配置文件中设置lazyLoadingEnabled=true(默认false),即可启用全局延迟加载;也可在ResultMap的association/collection标签中单独配置延迟加载规则。

19- 如何使用Mybatis实现批量插入 ?

Mybatis通过foreach标签实现批量插入,foreach标签可迭代集合并拼接SQL,核心步骤如下:

  1. 在insert标签中使用foreach标签遍历需要插入的集合;
  2. foreach标签的核心属性:
    • collection:指定要遍历的集合参数名(比如list、array);
    • item:迭代集合时,每个元素的别名(自定义变量名);
    • index:迭代过程中当前元素的索引(不常用);
    • open:指定拼接SQL的起始字符(比如"(");
    • separator:指定迭代元素之间的分隔符(比如",");
    • close:指定拼接SQL的结束字符(比如")");
  3. 拼接INSERT INTO ... VALUES (...)的批量插入SQL,完成批量插入。

20- Mybatis 批量插入是否能够返回主键

Mybatis批量插入可以返回生成的主键,主键值会自动封装到传入的集合中每个对象的主键属性里:例如批量插入List,插入后每个User对象的id(主键)属性会被赋值为数据库生成的自增主键。

21- Mybatis的一级、二级缓存 ?

Mybatis的缓存分为一级缓存和二级缓存,核心内容如下:

  1. 一级缓存:基于SqlSession级别的缓存,默认开启。同一个SqlSession中,多次执行相同的SQL查询,会将结果缓存到一级缓存中,后续查询直接从缓存获取,无需访问数据库;关闭SqlSession后,一级缓存失效;
  2. 二级缓存:基于SqlSessionFactory的NameSpace(命名空间)级别缓存,默认未开启,需手动配置:
    • 第一步:在Mybatis核心配置文件中开启全局二级缓存:;
    • 第二步:在Mapper映射文件中配置cache标签:(eviction为缓存淘汰策略,flushInterval为刷新间隔,size为缓存最大条目数);
      二级缓存跨SqlSession生效,同一个NameSpace下的多个SqlSession可共享缓存,提升查询效率。

总结

  1. SSM核心:Spring的IOC/DI实现对象解耦,事务基于AOP+数据库连接实现,需注意代理、异常捕获等导致的事务失效场景;
  2. SpringMVC核心是DispatcherServlet为中心的请求分发流程,常用注解简化请求映射和参数/响应处理;
  3. Mybatis核心是参数绑定(#{}防注入)、动态SQL、多表查询(association/collection)、缓存(一级默认开启,二级手动配置),批量操作依赖foreach标签实现。
相关文章
|
18天前
|
消息中间件 运维 监控
Kafka 最佳实践:分区策略、重试、幂等生产者
Kafka 最佳实践:分区策略、重试、幂等生产者
107 3
|
2月前
|
数据采集 人工智能 运维
AgentRun 实战:快速构建 AI 舆情实时分析专家
搭建“舆情分析专家”,函数计算 AgentRun 快速实现从数据采集到报告生成全自动化 Agent。
812 56
|
22天前
|
负载均衡 监控 Java
Spring Cloud 为什么是微服务时代中伟大的产物
Spring Boot 提升开发效率,但单体架构难以应对复杂业务。微服务通过拆分系统解决演进难题,而 Spring Cloud 以“抽象+插拔”模式整合服务发现、负载均衡、熔断等能力,推动微服务落地。OpenFeign 作为核心调用组件,串联治理链路,实现低侵入、高可用的分布式调用。
68 10
|
11天前
|
数据采集 人工智能 Java
核心目标:构建Java全流程AI Agent
在AI深度赋能企业背景下,依托JBoltAI框架,打造贯穿业务全链路的全流程AI Agent。突破传统自动化局限,实现跨模块协同、多系统融合与自适应迭代,推动Java生态智能化升级。
95 5
|
7天前
|
人工智能 NoSQL Java
你的 AI Agent 为什么总是“失忆”?揭秘 Spring AI 中的记忆管理陷阱与破局之道
Spring AI Agent常“失忆”?根源在于:1)HTTP无状态导致上下文丢失;2)未显式配置ConversationMemory;3)工具结果未回写记忆。本文剖析三大原因,提供Redis分布式记忆、sessionId绑定、工具结果自动注入等实战方案,并介绍滑动窗口、摘要压缩等高级技巧,助你打造真正连贯、可信的智能体。(239字)
113 1
|
16天前
|
关系型数据库 MySQL Java
Java微服务连接同个MySQL实例报错“Too many connections”
多个微服务共享同一MySQL实例时,易因连接池配置不当导致“Too many connections”错误。需综合评估max_connections限制与各服务连接池大小,合理调整数据库配置与应用参数,避免连接耗尽。
92 6
|
17天前
|
网络协议 Dubbo Java
从 TCP 到 RPC:彻底搞懂「HTTP 与 RPC用法区别」
本文深入剖析HTTP与RPC的本质区别,从TCP底层原理讲起,解析粘包拆包、协议封装等核心问题,梳理二者演进脉络。通过对比服务发现、传输性能、适用场景等维度,结合Dubbo、gRPC等框架,帮你按场景精准选型,彻底搞懂微服务通信的技术逻辑。
160 5
|
数据采集 前端开发 测试技术
如何爬取瀑布流网页加载的内容
本文探讨了爬取瀑布流网页内容的策略。首先解析了其工作原理——通过Ajax请求动态加载数据,并介绍了利用浏览器开发者工具分析这些请求的方法。随后,文章讲解了如何使用Python模拟这些请求,处理动态加载的内容,并推荐了Selenium等自动化工具以简化流程。最后强调了在爬虫开发过程中需遵守网站规定及道德准则的重要性。
|
供应链 数据挖掘
数据分析五大指标分类
数据分析中常见的指标分类方法
|
easyexcel
EasyExcel写入内容匹配不上解决方法
EasyExcel写入内容匹配不上解决方法
557 0