Skip to content

SSM 框架 待完善

什么是 SSM 框架?

SSM = Spring + Spring MVC + MyBatis

Spring 概述

什么是 Spring?

Spring 是一个分层的轻量级开源框架。

Spring 核心:控制翻转 IoC 和面向切面编程 AOP

IoC:Inversion of Control

AOP:Aspect Orient Programming

使用 Spring 的好处是什么?

提示

高耦合低内聚(通过DI)、模块化、AOP、集成框架、社区

  1. Spring 实现了高耦合低内聚,Spring 采用依赖注入的方式管理组件依赖关系。
  2. Spring 采用模块化设计,各个模块之间相互独立,可以灵活使用。
  3. 支持面向切片编程,将系统服务和业务逻辑分开
  4. Spring 对主流框架进行了集成和支持
  5. Spring 拥有庞大的开发者社区

Spring 有哪些模块,层次架构是怎样的?

Spring 具有七大模块。

  1. Spring Core:核心模块,实现 IoC 和 DI
  2. Spring Beans:管理 Bean 对象
  3. Spring Context:提供框架式的对象访问方法
  4. Spring JDBC:用于简化 JDBC 操作
  5. Spring AOP:提供面向切片编程
  6. Spring Web:支持 Web 开发
  7. Spring Test:集成 Junit 测试框架

Spring 用了哪些设计模式?

  1. 工厂模式:Spring 通过工厂模式使用 BeanFactory、ApplicationContext 创建 Bean 对象。
  2. 代理模式:Spring 使用代理模式实现了 AOP 面向切面编程。
  3. 单例模式:Spring 创建的 Bean 对象都是单例的,便于管理和使用。
  4. 模板模式:Spring 中提供了如 JDBCTemplate 的模板类。
  5. 观察者模式:Spring 事件驱动模型(类似消息队列)。
  6. 适配器模式:Spring MVC 使用了适配器模式适配 Controller,通过不同的实现类统一调用不同类型的实现类。
  7. 策略模式:Spring 有一个 Resource 接口,不同的实现类会以不同策略访问资源。

Spring IoC

什么是 IoC?说一说你对 IoC 的理解

提示

IoC 的核心是程序要依赖于接口,而不是具体实现类。

IoC 主要实现方式为 DI 依赖注入,程序代码只需要声明对象的依赖关系,Spring 容器负责创建对象和管理依赖。

IoC 是控制翻转。核心是程序要依赖于接口,而不是具体实现类。作用是降低代码耦合度。Spring IoC 是 Spring 框架的核心,用于管理 Bean 对象。

Spring 容器负责创建对象,管理依赖关系等,实现控制翻转。应用只需要声明对象依赖关系,降低了代码耦合度。

IoC 主要实现方式为 DI 依赖注入。对于依赖的对象,不通过 new 的方式创建对象,而是在外部创建好后传入。有 Setter 方法注入、构造方法注入、字段注入等方式。

另一种实现是依赖查找,通过容器的 API 查找依赖的对象。

什么是依赖注入 DI?

依赖注入是指,在需要其他对象时,不在代码中创建新对象,而是通过 Spring 容器传入已经创建好的对象。

IoC 的实现原理是什么?

提示

扫描注解 → 解析依赖 → 反射创建对象

  1. 扫描和解析配置或注解,转换成内部对象定义和依赖关系
  2. 根据关系使用反射动态创建对象,并注入到需要的地方

IoC 和 DI 有什么关系?

IoC 控制翻转是实现思想,DI 依赖注入是实现 IoC 的具体方式之一

Spring Bean

什么是 Spring Bean

Spring Bean 是托管在 Spring IoC 容器中的对象

Spring Bean 是 Spring 的基本单元,程序是由多个 Bean 对象构成的。

注入 Bean 的注解有哪些?

有两个,分别是 @Autowire@Resource

  1. Autowire 是 Spring 的注解,Resource 是 JDK 提供的注解
  2. Autowire 默认通过类型匹配,Resource 默认通过名称匹配
  3. Autowire 支持在构造函数、方法、字段和参数上注入,Resource 只能在字段和方法上注入。
  4. 当一个接口有多个实现类,两者都需要通过指定名称,可以显式(注解中指定)和隐式(变量名)声明。

将一个类声明为 Bean 的方式有什么?

  1. @Component:任意类
  2. @Repository:Dao 层
  3. @Service:服务层
  4. @Controller:MVC 控制器层

Bean 的作用域有哪些?

  1. singleton(单例)
  2. prototype(原型):每次获取都创建新实例
  3. request(请求):每次 HTTP 请求都会创建新实例,在当前 HTTP 请求内有效。
  4. session(会话):每个 HTTP 会话都会创建新实例,在当前会话内有效
  5. websocket:每次 ws 产生新实例
  6. global session(全局会话):在 Web 应用运行中有效。

Bean 的生命周期是什么

  1. 实例化:通过反射创建对象,调用无参构造方法
  2. 属性赋值:依赖注入
  3. 初始化:执行初始化逻辑
    1. 初始化前:@PostConstruct
    2. 初始化:继承 InitializingBean
    3. 初始化后:执行 AOP
  4. 使用 Bean 实例
  5. 销毁

什么是 FactoryBean?

FactoryBean 是 Spring 提供的一种创建 Bean 的方式。

可以通过实现 FactoryBean 接口中的 getObject() 方法来返回一个 Bean 对象。

BeanFactory 和 FactoryBean 区别是什么?

BeanFactory:用于创建和管理 Bean 实例

用于策略模式中,通过名称在 BeanFactory 中获取 Bean。

FactoryBean:一种创建 Bean 的方式

一个实现 FactoryBean 接口的特殊 Bean,负责创建其它的 Bean。

BeanFactory 和 ApplicationContext 的关系是什么?

BeanFactory 是 Spring 框架中的容器,提供 IoC 和 DI 的支持,用于⽣成Bean、维护Bean。

ApplicationContext 基于 BeanFactory,并提供了更多的功能和特性,比如获取系统环境变量、国际化、事件发布等。

Bean 是线程安全的吗?

对于多例 Bean(原型 Bean),每次获取都会生成新的对象,所以是线程安全的。

对于单例 Bean,对于无状态(不包含可变的成员变量)的 Bean 是线程安全的。如果需要包含成员变量,可以使用 ThreadLocal 保存成员变量保证安全。

❓Spring 的三级缓存是什么?

TDB...

❓为什么 Spring 需要三级缓存?

TDB...

❓Spring 如何解决循环依赖的问题?

TDB...

❓Spring 可以存在两个 ID 相同的 Bean 吗?

TDB...

Spring AOP

什么是 AOP?

AOP 是面向切片编程。通过代理的方式,在方法调用时进行拦截处理,先执行切入的逻辑,再调用方法。

说一说对 AOP 的理解

AOP 面向切片编程通过在运行期间动态代理目标对象,将横切关注点织入到系统中,实现了业务逻辑与横切关注点的分离。

AOP 有哪些实现方式?

AOP 分为静态代理和动态代理。

  • 静态代理:在编译期生成代理类,比如 AspectJ。代理对象需要和目标对象实现相同的接口,需要维护两个类的代码。
  • 动态代理:在运行时动态生成代理类。
    • JDK 动态代理:必须实现一个接口,通过反射实现。
    • CGLIB 动态代理:通过继承的方式生成代理子类

Spring AOP 和 AspectJ AOP 有什么区别?

Spring AOP 是运行时增强,AspectJ AOP 是编译时增强。

AspectJ AOP 有更好的性能。

谈一谈动态代理

Java 动态代理可以在运行时动态生成代理类和对象,无需编写静态代理类。

  1. JDK 动态代理:基于接口的动态代理
  2. CGLIB 动态代理:基于类的动态代理

JDK 动态代理和CGLIB 动态代理的差异

Spring 注解

有哪些常用的 Spring 注解

  1. 控制器类:@Controller、@RestController、@RequestMapping、@PathVariable、@ResponseBody
  2. 服务类:@Service
  3. 依赖注入:@Resource、@Autowired
  4. 声明 Bean:@Bean
  5. 切面编程:@Aspect、@Before、@After、@Around

@Componet 和 @Bean 的区别?

@Component 可以用在类上,通过类路径扫描注入到 Spring 容器。

@Bean 用在方法上,在配置类中声明单个 Bean 对象。

@Configuration 和 @Component 有什么区别?

@Component 用于将该类定义为 Bean。

@Configuration 该类内部的方法可以使用 @Bean 注解来定义 Bean。

@Required 注解有什么用?

@Required 注解用于标注在 Spring Bean 的 setter 方法上,表示该属性是必须的。

java
public class MyBean {
    private String name;

    @Required
    public void setName(String name) {
        this.name = name;
    }
}

@Autowired 和 @Qualifier 注解有什么用?

@Autowired:用于自动装配 Bean,可以标注在字段、setter 方法或者构造方法上

@Qualifier:与 @Autowired 结合使用,用于在有多个相同类型的 Bean 时,指定具体要注入的 Bean

java
public class MyService {
    @Autowired
    @Qualifier("specificBeanName")
    private MyRepository myRepository;
}

@RequestMapping 注解有什么用?

用于将特定的 HTTP 请求方法和路径映射到特定的方法和类上。

  1. 用于类上:映射当前类请求的 URL
  2. 用于方法上:映射当前方法请求的 URL 和 HTTP 请求方法

@Controller 注解有什么用?

@Controller 注解用来标记该类为 Spring MVC 控制器类。Spring 会扫描该类中标记 @RequestMapping 的方法,创建控制器对象。

@RestController 和 @Controller 有什么区别?

@RestController@Controller 的基础上添加了 @ResponseBody 注解。适合使用在前后端分离架构中,提供 Restful API 并返回 JSON 数据。

@RequestParam 和 @PathVariable 两个注解的区别?

@RequestParam:在请求 URL 中携带的参数获取

@PathVariable:在请求 URL 路径中获取

❓Spring 事务

Spring 实现事务方式有什么?

  1. 编程式事务:通过 TransactionTemplateTransactionManager 手动管理事务
  2. 声明式事务
    1. 创建事务管理器
    2. 在接口方法上使用 @Transactional 注解
    3. 在配置类中声明开启事务注解 @EnableTransactionManagement

Spring MVC

什么是 Spring MVC?

Spring MVC 是一个实现了 MVC 模型的请求驱动型 Web 框架。

MVC 模型是把 "模型-视图-控制器" 分离,通过职责进行解耦。

请求驱动型:在接收到请求后,会执行相应的操作并返回结果

说一说 Spring MVC 的执行流程

  1. 用户发送出请求到前端控制器 DispatcherServlet(前端控制器)
  2. DispatcherServlet(前端控制器)收到请求调用 HandlerMapping(处理器映射器)
  3. HandlerMapping(处理器映射器)找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给 DispatcherServlet(前端控制器)
  4. DispatcherServlet(前端控制器)调用 HandlerAdaptor(处理器适配器)
  5. HandlerAdaptor(处理器适配器)经过适配调用具体的处理器(Handler/Controller)

HandlerMapping(处理器映射器):将请求路由到正确的处理器。

HandlerAdapter(处理器适配器):调用 Handler 的方法来处理请求。

返回视图 View 的流程:

Spring MVC 拦截器是什么?

Spring MVC 拦截器是一种机制,用于在请求和响应进行预处理和后处理。

常用于一些场景:

  1. 鉴权
  2. 刷新 token 有效期
  3. 重定向
  4. 缓存
  5. 记录日志 / 计算请求时长

Spring MVC 如何配置拦截器?

实现 HandlerInterceptor 接口,在 MVC 配置类中添加拦截器,配置拦截路径。

过滤器和拦截器的差异?

  1. 使用范围
    1. 过滤器是 Servlet 规范,依赖于 Tomcat 容器
    2. 拦截器是 Spring 组件
  2. 触发时机:先触发过滤器,再触发拦截器
  3. 底层实现
    1. 过滤器通过方法回调实现
    2. 拦截器通过动态代理反射实现

如何实现拦截器?

过滤器可以使用 @WebFilter 注解,配置过滤的 URL 规则,实现Filter接口,再重写接口中的 vdoFilter 方法。

java
@Component
@WebFilter("/*") // 这个过滤器将拦截所有请求
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 过滤器初始化逻辑(如果有需要的话)
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        // 在请求到达目标 Servlet 之前执行一些操作
        System.out.println("Request intercepted by MyFilter");

        // 继续执行过滤链
        chain.doFilter(request, response);
        
        // 在响应返回给客户端之前执行一些操作
        System.out.println("Response intercepted by MyFilter");
    }

    @Override
    public void destroy() {
        // 过滤器销毁逻辑(如果有需要的话)
    }
}

说一说 Spring MVC 异常处理

异常处理可以拦截和处理控制器中的异常,返回自定义的错误响应。

  1. @RestControllerAdvice:返回 JSON
  2. @ControllerAdvice:返回视图或模板
java
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(RuntimeException.class)
    public BaseResponse handleRuntimeException(RuntimeException e) {
        return ResponseUtils.error("API Error: RuntimeException");
    }
}

MyBatis

什么是 MyBatis?

Mybatis 是一个封装了 JDBC 的 ORM 框架,用于数据库的数据和 Java 对象的映射。

MyBatis 的优点是什么?

  1. 基于 SQL,使用灵活
  2. 降低了 JDBC 的使用成本
  3. 实现数据库数据和 Java 对象的映射

Mybatis 和 Hibernate 的区别是什么?

MyBatis 是半自动化 ORM 框架,需手写 SQL,精细度较高。

Hibernate 是全自动化 ORM 框架,生成 SQL 并提供完整的对象关系映射。

MyBatis 使用了哪些设计模式?

  1. 缓存模块使用了装饰器模式,通过多个装饰类对缓存对象进行增强
  2. 日志模式使用了适配器模式(策略模式),适配 SLF4J、Log4J等
  3. BaseExecutor 使用了模板方法模式,实现了大部分的 SQL 执行逻辑
  4. Mapping 使用了代理模式
  5. 反射模块使用了工厂模式和装饰器模式
  6. SqlSessionFactoryBuilder 使用了建造者模式
  7. ErrorContext 用于记录错误信息,是线程级别的单例模式

MyBatis 工作原理是什么?

  1. 加载 Mybatis 全局配置文件(mybatis-config.xml)和映射文件(xxxMapper)
  2. 构造会话工厂 SqlSessionFactory,创建会话对象 SqlSession
  3. 调用 SqlSession 提供的执行器,执行 Mapper 中定义的 SQL 操作数据库
  4. 将输入输出参数映射到 Java 对象

介绍一下 MyBatis 的缓存

MyBatis 的缓存可以减低数据库的负载,提高响应速度。

MyBatis 的缓存使用了装饰者模式,用于扩展缓存的功能。

Mybatis 默认使用一级缓存(Session 级别),且支持二级缓存(SqlSessionFactory 级别 / 进程级别)。

缓存顺序:二级缓存 → 一级缓存 → 数据库。

先查询二级缓存的原因:二级缓存是 SqlSessionFactory 级别,缓存的内容比一级缓存多,提高查询效率。

在 mybatis-config.xml 中配置缓存。

Mybatis 都有哪些 Executor 执行器?

  1. SimpleExecutor:每次执行都创建 Statement 对象,用完关闭。
  2. ReuseExecutor:创建完 Statement 对象存入 map 复用。
  3. BatchExecutor:批量创建 Statement 对象,用于批处理。

Mybatis 是否支持延迟加载?原理是什么?

MyBatis 支持延迟加载

延迟加载:多表联查时,如果暂时没有用到其他表的信息,就先不查询,当用到的时候在查询。提高性能。

延迟加载的原理:使用 CGLIB 创建代理对象,当调用 get 返回 null 时,就会进行 SQL 查询,并 set 值。

什么是 MyBatis 的接口绑定?有哪些实现方式?

接口绑定是 MyBatis 中,将接口和 SQL 语句绑定,查询时直接调用方法。

有两种绑定方式:

  1. 在接口上使用注解,比如 @Select、@Update
  2. 使用 xml 配置绑定,namespace 需要是接口的全路径名

Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式?

  1. 通过 resultMap 映射,逐一定义列名和属性字段关系。
  2. 通过 sql 列别名,通过别名找到属性字段

之后通过反射的方式创建对象,并对其赋值。

MyBatis 是如何进行分页的?原理是什么?

为什么需要分页:用户不需要太多数据,且数据多的性能较差。通过拼接 limit 关键字实现分页。

MyBatis 实现分页的方式:

  1. 逻辑分页:使用 RowBounds 进行内存分页(没啥用)
  2. 物理分页:通过拦截器或插件实现

MyBatis 实现分页的原理:通过拦截器拼接 limit 0, 10

Spring Boot

Spring Boot 是什么?有什么特点

Spring Boot 是一个基于 Spring 的框架,简化了 Spring 框架的配置、搭建和开发。类似于脚手架。

特点:

  1. 根据依赖进行自动配置,比如数据库连接
  2. 内嵌了 Tomcat 容器,可以直接打包运行,不依赖其他容器
  3. 提供了 starter 依赖,可以快速整合依赖
  4. 不需要 Spring 和 Spring MVC 繁琐的配置文件

Spring Boot 核心注解

  1. @SpringBootApplication:Spring Boot 主启动类
  2. @SpringBootConfiguration:Spring Boot 配置类,用于定义 Bean
  3. @ComponentScan:定义 Spring 包扫描路径,实现 Bean 的自动配置

谈一谈 Spring Boot 自动装配

自动装配是值,通过项目依赖自动创建并配置所需的 Bean,无需手动编写 XML 或配置类来设置 Spring 容器。

比如添加了 spring-boot-starter-web 依赖之后,Spring Boot 会自动配置一个 Servlet 容器以及相关的 Web 环境所需的 Bean,简化开发流程。

Spring Boot 自动化配置的原理是什么?

  1. 主启动类 @SpringBootApplication 注解中包含 @EnableAutoConfiguration 注解。启动后会加载 AutoConfigurationlmportSelector.class。
  2. 这个类会加载所有 jar 包中 META-INF/spring-factories 配置文件、
  3. SpringBoot 会通过配置信息,按需加载 @Configuration 配置类,创建并自动注入 Bean。

❓说一说 Spring Boot 启动流程

Spring Boot 项目如何热部署?

热部署:不重启应用的情况下,重新加载更新的代码。

通过添加 devtools 依赖实现,常用于开发环境。

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

Spring Boot 打包成的 jar 和普通的有什么区别?

Spring Boot 项目最终打包成的 jar 包是可执行的 jar 包。

这种 jar 包可以直接通过 java-jar xxx.jar 命令来运行,但是这种 jar 包不可以作为普通的 jar 包被其他项目依赖,无法使用其中的类。

Released under the MIT License.