Spring、SpringMVC 与 MyBatis 核心知识点解析

简介: 我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态

Spring 相关

  1. Spring IOC 和 DI
  • IOC(控制反转):简单说就是把原来程序里自己创建对象、管理对象调用的权力,交给了 Spring 容器。原来我们在代码里直接 new 对象,现在由容器来负责对象的创建、装配和管理,对象的控制权从代码转移到了外部容器。
  • DI(依赖注入):在创建对象的时候,容器会把这个对象所依赖的其他属性(比如其他对象、值等)自动填充到类里面。
  1. 依赖注入的实现方式
  • 有接口注入、Setter 方法注入和构造器注入这三种。
  • 构造器依赖注入:容器通过调用类的构造器来实现,构造器里的每个参数都代表着对其他类的依赖。
  • Setter 方法注入:容器先通过无参构造器或者无参的 static 工厂方法创建出 bean,然后调用这个 bean 的 setter 方法来完成注入。
  1. Spring 中 bean 的作用域(Scope)
  • Spring 支持五种作用域:
  • singleton:在每个 Spring IOC 容器里,这个 bean 只有一个实例。
  • prototype:一个 bean 定义可以有多个实例。
  • request:每次 HTTP 请求都会创建一个新的 bean,只在基于 web 的 Spring ApplicationContext 里有效。
  • session:在一个 HTTP Session 中,一个 bean 定义对应一个实例,同样只在基于 web 的 Spring ApplicationContext 里有效。
  • global-session:在全局的 HTTP Session 中,一个 bean 定义对应一个实例,也是仅在基于 web 的 Spring ApplicationContext 里有效。
  1. Spring 单例 bean 的线程安全性
  • 单例 bean 本身不是线程安全的,因为 Spring 框架没有对单例 bean 做多线程的封装处理。不过我们平时用单例 bean 时,一般不会设置共享数据,所以通常不会有线程安全问题,从这方面看也能说它是线程安全的。
  1. Spring 自动装配 bean 的方式
  • 在 xml 配置里有五种自动装配方式:
  • byName:根据 bean 的名称来自动装配,如果一个 bean 的 property 和另一个 bean 的 name 相同,就会进行装配。
  • byType:按照参数的数据类型来自动装配。
  • constructor:利用构造函数进行装配,而且构造函数的参数是通过 byType 来匹配的。
  1. Spring 事务的实现
  • 底层是基于数据库事务和 AOP 机制实现的。
  • 对于加了 @Transactional 注解的 Bean,Spring 会创建一个代理对象。当调用代理对象的方法时,会先判断方法上有没有 @Transactional 注解。
  • 如果有的话,就用事务管理器创建一个数据库连接,并且把这个连接的 autocommit 属性设为 false,禁止自动提交。
  • 然后执行当前方法里的 SQL,执行完如果没出现异常就提交事务,出现需要回滚的异常就回滚,否则还是提交。
  • 事务的隔离级别和数据库的隔离级别对应,而传播机制是 Spring 自己实现的,基于数据库连接,一个连接对应一个事务,要是传播机制要求新开事务,就新建一个数据库连接来执行 SQL。
  1. Spring 事务失效的场景
  • 因为事务是基于代理实现的,所以加了 @Transactional 的方法只有被代理对象调用时才生效,被代理对象自己调用的话会失效。
  • 如果方法是 private 的,@Transactional 也会失效,因为 CGLIB 代理是基于父子类,子类不能重载父类的 private 方法,没法很好地代理。
  • 业务中如果自己捕获了异常,Spring 感知不到异常,事务也会失效。
  1. Spring 事务的传播行为
  • PROPAGATION_REQUIRED:当前没事务就新建一个,有就加入,这是最常用的。
  • PROPAGATION_SUPPORTS:支持当前事务,有就加入,没有就以非事务方式执行。
  • PROPAGATION_MANDATORY:必须要有当前事务,有就加入,没有就抛异常。
  • PROPAGATION_REQUIRES_NEW:不管当前有没有事务,都新建一个事务。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行,有当前事务就把它挂起。
  • PROPAGATION_NEVER:以非事务方式执行,有当前事务就抛异常。
  • PROPAGATION_NESTED:当前有事务就在嵌套事务里执行,没有就按 REQUIRED 的规则来。
  1. JDK 动态代理和 CGLIB 动态代理的区别
  • 这是 Spring AOP 里的两种动态代理方式:
  • JDK 动态代理:只支持对接口的代理,用 Proxy.newProxyInstance (类加载器,代理对象实现的所有接口,代理执行器) 来创建代理。
  • CGLIB 动态代理:通过继承的方式实现,要是类被标记为 final,就不能用它来代理了,用 Enhancer.create (父类的字节码对象,代理执行器) 来创建代理。
  1. AOP 及项目中的使用
  • AOP(面向切面编程):作为面向对象的补充,把那些和业务无关但对多个对象有影响的公共逻辑(比如日志、权限等)抽取出来做成一个可重用的 “切面”,这样能减少重复代码,降低模块耦合度,方便维护。
  • 项目中自己写 AOP 的情况不多,但很多框架功能底层都用到了,比如权限认证、日志记录、事务处理等。

SpringMVC 相关

  1. SpringMVC 的执行流程
  • 用户发请求给前端控制器 DispatcherServlet。
  • DispatcherServlet 调用 HandlerMapping 处理器映射器获取 Handler。
  • 处理器映射器根据请求 url 找到具体处理器,生成处理器对象和拦截器(如果有的话)返回给 DispatcherServlet。
  • DispatcherServlet 调用 HandlerAdapter 处理器适配器。
  • HandlerAdapter 适配后调用具体的处理器(Handler)。
  • Handler 执行完返回 ModelAndView。
  • HandlerAdapter 把 ModelAndView 返回给 DispatcherServlet。
  • DispatcherServlet 把 ModelAndView 传给 ViewResolver 视图解析器解析。
  • ViewResolver 解析后返回具体的 View。
  • DispatcherServlet 对 View 进行渲染(填充模型数据)。
  • 最后 DispatcherServlet 响应给用户。
  1. Spring MVC 常用的注解
  • @RequestMapping:处理请求 url 映射,可用于类或方法,类上的话就是父路径。
  • @RequestBody:接收 http 请求的 json 数据,把 json 转成 java 对象。
  • @ResponseBody:把控制器方法返回的对象转成 json 响应给客户。
  • @Controller:标记控制器,属于表现层,不能用其他注解代替。
  • @RestController:是 @Controller + @ResponseBody 的组合注解。
  • @GetMapping@PostMapping@PutMapping@DeleteMapping等:对应不同 HTTP 方法的请求映射。
  • @PathVariable:接收请求路径中的变量。
  • @RequestParam:接收请求参数。

MyBatis 相关

  1. Mybatis #{} 和 ${} 的区别
  • #{} 是占位符,会做预编译处理;${} 是拼接符,做字符串替换,不预编译。
  • MyBatis 处理 #{} 时,会把 SQL 里的 #{} 换成?,用 PreparedStatement 的 set 方法赋值,能防止 SQL 注入,安全性高,变量替换在数据库系统中进行。
  • ${} 不能防止 SQL 注入,变量替换在数据库系统外进行。
  1. Mybatis 获取生成的主键
  • 有两种方式:
  • 在 insert 标签上用 useGeneratedKeys="true" 和 keyProperty="userId"。
  • 在 insert 标签内部用 selectKey 标签,里面用 select last_insert_id () 查询生成的 ID 返回。
  1. 实体类属性名和表字段名不一样的解决办法
  • 第一种:在查询 SQL 里给字段名起别名,让别名和实体类属性名一致。
  • 第二种:通过 ResultMap 来映射字段名和实体类属性名。
  1. Mybatis 实现多表查询的方式
  • 第一种:写多表关联查询的 SQL,用 ResultMap 建立结果集映射,里面用 association(一对一)和 collection(一对多)标签。
    例如:
  1. xml
<resultMap id="Account_User_Map" type="com.heima.entity.Account">
    <id property="id" column="id"></id>
    <result property="uid" column="uid"></result>
    <result property="money" column="money"></result>
    <association property="user">
        <id property="id" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
    </association>
</resultMap>
<select id="findByIdWithUser" resultMap="Account_User_Map">
    select  a.*,  username, birthday, sex, address  from account a , user u where a.UID = u.id and a.ID = #{id} ;
</select>
  • 第二种:把多表查询拆成多个单表查询,在 ResultMap 的 association 或 collection 标签里用 select 属性指定另一条 SQL 的定义去执行,结果会自动封装。
    例如:
  1. xml
<resultMap id="Account_User_Map" type="com.heima.entity.Account" autoMapping="true">
    <id property="id" column="id"></id>
    <association property="user" select="com.heima.dao.UserDao.findById" column="uid" fetchType="lazy"></association>
</resultMap>
<select id="findByIdWithUser" resultMap="Account_User_Map">
    select * from account where  id = #{id}
</select>
  1. Mybatis 的动态 sql 及执行原理
  • 动态 sql 是在 Xml 映射文件里用标签写的,能做逻辑判断和动态拼接 sql,有 trim、where、set、foreach、if、choose、when、otherwise、bind 这 9 种标签。
  • 执行原理是用 OGNL 从 sql 参数对象里计算表达式的值,根据值来动态拼接 sql。
  1. Mybatis 对延迟加载的支持
  • 只支持 association(一对一)和 collection(一对多)的延迟加载,在配置文件里通过设置 lazyLoadingEnabled=true|false 来启用或关闭。
  1. Mybatis 实现批量插入
  • 用 foreach 标签,它能迭代集合,属性有:
  • collection:要遍历的集合。
  • item:迭代时每个元素的别名。
  • index:迭代位置,不常用。
  • open:语句的开始部分。
  • separator:迭代元素之间的分隔符。
  • close:语句的结束部分。
  1. Mybatis 批量插入能否返回主键
  • 可以,返回的主键会封装在传入集合的每个对象的属性里。
  1. Mybatis 的一级、二级缓存
  • 一级缓存:基于 SqlSession 级别,默认开启。
  • 二级缓存:基于 SqlSessionFactory 的 NameSpace 级别,默认不开启,需要手动开启:
  • 在配置文件里设置 cacheEnabled 为 true:
  • xml
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
  • image.png
  • 在映射配置文件里配置 cache 相关:
  • xml
<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>
  • image.png
相关文章
|
7月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
11月前
|
Java 数据库连接 API
Java 对象模型现代化实践 基于 Spring Boot 与 MyBatis Plus 的实现方案深度解析
本文介绍了基于Spring Boot与MyBatis-Plus的Java对象模型现代化实践方案。采用Spring Boot 3.1.2作为基础框架,结合MyBatis-Plus 3.5.3.1进行数据访问层实现,使用Lombok简化PO对象,MapStruct处理对象转换。文章详细讲解了数据库设计、PO对象实现、DAO层构建、业务逻辑封装以及DTO/VO转换等核心环节,提供了一个完整的现代化Java对象模型实现案例。通过分层设计和对象转换,实现了业务逻辑与数据访问的解耦,提高了代码的可维护性和扩展性。
418 1
|
10月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
704 0
|
10月前
|
JSON 前端开发 Java
第05课:Spring Boot中的MVC支持
第05课:Spring Boot中的MVC支持
395 0
|
10月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
1339 0
|
11月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
1162 0
|
7月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
583 4
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
530 0
|
7月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
1106 3