}

}

context:annotation-config/

4 Spring bean 的生命周期

其中有颜色的部分是重要的,口语化的表达,其生命周期为

  1. 首先是 bean 的实例化,创建一个 bean 对象;

  2. 然后是进行属性的填充;

  3. 然后是 bean 的初始化阶段,其中包括 Aware 接口的触发、执行 init-method 属性指定的方法等;

  4. 再是 bean 的正常使用阶段;

  5. 最后是 bean 的销毁阶段。

详细来说就是:

  • Bean 容器找到配置文件中 Spring Bean 的定义。

  • Bean 容器利用 Java Reflection API 创建一个Bean的实例。

  • 如果涉及到一些属性值 利用 set()方法设置一些属性值。

  • 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。

  • 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。

  • 如果Bean实现了 BeanFactoryAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoade r对象的实例。

  • 与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。

  • 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法

  • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。

  • 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。

  • 如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法

  • 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。

  • 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。

5 bean 的作用域

6 Spring 中的单例 bean 的线程安全问题了解吗?

大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。

常见的有两种解决办法:

  1. 在Bean对象中尽量避免定义可变的成员变量(不太现实);

  2. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

7 @Component 和 @Bean 的区别

  1. 作⽤对象不同: @Component 注解作⽤于类,⽽ @Bean 注解作⽤于⽅法;

  2. @Component 通常是通过类路径扫描来⾃动侦测并⾃动装配到 Spring 容器中(我们可以使⽤ @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类⾃动装配到 Spring 的 bean 容器中)。 @Bean 注解通常是我们在标有该注解的⽅法中定义产⽣这个 bean,@Bean 告诉了Spring 这是某个类的示例,当我需要⽤它的时候还给我;

  3. @Bean 注解⽐ Component 注解的⾃定义性更强,⽽且很多地⽅我们只能通过 @Bean 注解来注册 bean,⽐如当我们引⽤第三⽅库中的类需要装配到 Spring 容器时,则只能通过 @Bean 来实现。

1.4 Spring 事务


1 说一下 Spring 管理事务的方式

  1. 编程式事务,在代码中硬编码(不推荐使用);

  2. 声明式事务,在配置文件中配置(推荐使用);

声明式事务又分为两种:

  1. 基于 XML 的声明式事务;

  2. 基于注解的声明式事务;

2 事务的实现原理

Spring 事务的底层实现主要使用的技术:AOP(动态代理) + ThreadLocal + try/catch。

  • 动态代理:基本所有要进行逻辑增强的地方都会用到动态代理,AOP 底层也是通过动态代理实现;

  • ThreadLocal:主要用于线程间的资源隔离,以此实现不同线程可以使用不同的数据源、隔离级别等等;

  • try/catch:最终是执行 commit 还是 rollback,是根据业务逻辑处理是否抛出异常来决定。

Spring 事务的核心逻辑伪代码如下:

public void invokeWithinTransaction() {

// 1.事务资源准备

try {

// 2.业务逻辑处理,也就是调用被代理的方法

} catch (Exception e) {

// 3.出现异常,进行回滚并将异常抛出

} finally {

// 现场还原:还原旧的事务信息

}

// 4.正常执行,进行事务的提交

// 返回业务逻辑处理结果

}

详细流程如下图所示:

3 说一下 Spring 事务中的隔离级别

TransactionDefinition 接口中定义了五个表示隔离级别的常量:

  • TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ 隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别;

  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

  • TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

  • TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生

  • TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

4 Spring 事务中有哪几种事务传播行为

一共是七种,按照是否支持当前事务,可以分为以下情况:

支持当前事务的情况:

  • TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务;

  • TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

  • TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

不支持当前事务的情况:

  • TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。

  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。

  • TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。

其他情况:

  • TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

5 Spring 的事务隔离级别是如何做到和数据库不一致的

比如数据库是可重复读,Spring 是读已提交,这是怎么实现的?

**Spring 的事务隔离级别本质上还是通过数据库来控制的,具体是在执行事务前先执行命令修改数据库隔离级别,**命令格式如下:

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED

2 Spring MVC

===============================================================================

1 什么是 MVC

还记得之前的 JavaWeb 的项目中,里面的 Web 层、Service 层以及 Dao 层是否还有印象。

在 Spring MVC 下,我们⼀般把后端项⽬分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台⻚⾯)。

接下来,我们就开始学习 SSM 框架,即 Spring + Spring MVC + MyBatis。它们与模型层次分别一一对应。

拓展:过去的 MVC 模型就是 jsp + servlet + javabean 模式,其中:

  • JavaBean 作为模型,既可以作为数据模型来封装业务数据,又可以作为业务逻辑模型来包含应用的业务操作。其中,数据模型用来存储或传递业务数据,而业务逻辑模型接收到控制器传过来的模型更新请求后,执行特定的业务逻辑处理,然后返回相应的执行结果;

  • JSP 作为视图层,负责提供页面为用户展示数据,提供相应的表单(Form)来用于用户的请求,并在适当的时候(点击按钮)向控制器发出请求来请求模型进行更新;

  • Serlvet 作为控制器,用来接收用户提交的请求,然后获取请求中的数据,将之转换为业务模型需要的数据模型,然后调用业务模型相应的业务方法进行更新,同时根据业务执行结果来选择要返回的视图;

2 SpringMVC 的核心入口类是什么

DispatchServlet。

3 SpringMVC 的控制器是不是单例模式,如果是,有什么问题,怎么解决

是单例模式,所以在多线程访问的时候有线程安全问题,不过不能使用同步,因为会影响性能的,解决方案是在控制器里面不能写字段。

4 SpingMVC 中的控制器的注解一般用哪个,有没有别的注解可以替代

一般用 @Conntroller 注解,不能用别的注解代替。

5 @RequestMapping 注解用在类上面有什么作用

其用于类上,表示类中的所有请求与响应的方法都是以该地址作为父路径。

6 怎么样把某个请求映射到特定的方法上面

直接在方法上面加上注解 @RequestMapping,并且在这个注解里面写上要拦截的路径。

7 直接在方法上面加上注解 @RequestMapping,并且在这个注解里面写上要拦截的路径。

可以在 @RequestMapping 注解里面加上 params=”type=test”

8 如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象

直接在方法中声明这个对象,SpringMVC 就自动会把属性赋值到这个对象里面。

3 MyBatis

============================================================================

1 说一说什么是 MyBatis

Mybatis 是一个半 ORM(对象关系映射)的持久层框架,它内部封装了JDBC、加载驱动、创建连接、创建 statement 等繁杂的过程,开发者开发时只需要关注如何编写 SQL 语句,可以严格控制 SQL 执行性能,灵活度高。

可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类(POJO) 【Plain Old Java Objects】映射成数据库中的记录,几乎避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程。

2 那什么是持久化

持久化是将程序数据在持久状态和瞬时状态间转换的机制,即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)的机制。

之所以需要持久化,是因为内存本生是不可靠的,可能会导致某些数据丢失。同时,也会因为

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

内存的容量限制不能一直呆在内存中,需要持久化来缓存到外存。

参考文献:传送门

3 为什么说 MyBatis 是半自动的 ORM 映射工具

Hibernate 属于全⾃动 ORM 映射⼯具,使⽤ Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全⾃动的。而 Mybatis 在查询关联对象或关联集合对象时,需要⼿动编写 sql 来完成,所以,称之为半⾃动 ORM 映射⼯具

4 #{} 和 ${} 的区别是什么

#{} 是预编译处理,${} 是字符串替换。MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为 ? 号,使用 PreparedStatement 的 setter 方法来赋值,MyBatis在处理 ${ } 时,就是把 ${ } 替换成变量的值。

同时,使用 #{} 可以有效的防止 SQL 注入,提高系统安全性。

5 MyBatis 的配置解析

MyBatis 的配置就相当于配置其的配置文件。

MyBatis 具有如下的配置信息:

  • properties(属性)

  • settings(设置)

  • typeAliases(类型别名)

  • typeHandlers(类型处理器)

  • objectFactory(对象工厂)

  • plugins(插件)

  • environments(环境配置)

  • environment(环境变量)

  • transactionManager(事务管理器)

  • dataSource(数据源)

  • databaseIdProvider(数据库厂商标识)

  • mappers(映射器)

详细内容可以参考博客:传送门

6 XML 映射文件中,有哪些常用的标签

cache – 该命名空间的缓存配置。

cache-ref – 引用其它命名空间的缓存配置。

resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。

sql – 可被其它语句引用的可重用语句块。

insert – 映射插入语句。

update – 映射更新语句。

delete – 映射删除语句。

select – 映射查询语句。

7 一个 MyBatis 程序的过程(Java 代码部分)

/**

  • 通过 Mybatis 的官方教程:https://mybatis.org/mybatis-3/zh/getting-started.html

*/

public class MyBatisUtils {

private static SqlSessionFactory sqlSessionFactory;

static {

try {

// 1 从 XML 中构建 SqlSessionFactory

String resource = “mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

} catch (IOException e) {

e.printStackTrace();

}

}

//获取SqlSession连接

public static SqlSession getSession(){

return sqlSessionFactory.openSession();

}

}

package sharm.dao;

import org.apache.ibatis.session.SqlSession;

import org.junit.Test;

import sharm.pojo.User;

import sharm.utils.MyBatisUtils;

import java.util.List;

public class UserTest {

@Test

public void testSelectUser(){

//2 从 SqlSessionFactory 中获取 SqlSession

SqlSession session = MyBatisUtils.getSession();

//3 探究已映射的 SQL 语句

UserMapper mapper = session.getMapper(UserMapper.class);

List users = mapper.selectUser();

for (User user: users){

System.out.println(user);

}

session.close();

}

}

8 MyBatis 的生命周期

  1. SqlSessionFactoryBuilder 通过配置文件生成 SqlSessionFactory,一旦创建完后,就可以销毁它;

  2. SqlSessionFactory 在 MyBatis 中以单例模式存在,创建于程序开始,销毁于程序结束,类似于线程池;

  3. SqlSession 类似于线程池中的一个线程,线程结束后就归还于线程池;

  4. Mapper 是 SqlSession 创建的一个具体的业务,一旦处理完了这个业务,就可以销毁它。

一个 SqlSessionFactory 会有很多 SqlSession,同理 SqlSession 也会有很多 Mapper。

9 MyBatis 的作用域

| 类名 | 作用域 |

| :-: | :-: |

| SqlSessionFactoryBuilder | 方法作用域 |

| SqlSessionFactory | 全局作用域 |

| SqlSession | 方法作用域 |

| Mapper | 方法作用域 |

10 Mybatis 是如何进行分页的?分页插件的原理是什么?

三种分页方式:

  1. 使用 limit 进行分页;

  2. 使用 RowBounds 分页,这个属于逻辑分页,即实际上 sql 查询的是所有的数据,在业务层进行了分页而已,比较占用内存,而且数据更新不及时,可能会有一定的滞后性;

  3. 使用分页插件(jar 包)进行分页;

分页插件的基本原理是在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据dialect 方言,添加对应的物理分页语句和物理分页参数。

11 说一说 MyBatis 的缓存

缓存指的是存在于内存中的临时数据。使用缓存,可以减少和数据库的交互次数,减少系统开销,提高系统效率。经常被查询且不经常改变的数据可以使用缓存来存储。

MyBatis 中默认定义了两级缓存:一级缓存和二级缓存。

  • 一级缓存,又称为本地缓存,是 SqlSession 级别的缓存,默认情况下是开启的;

  • 二级缓存是基于 namespace 级别的缓存,则需要手动开启和配置。

当一个会话查询一条数据时,这个数据就会放在当前会话的一级缓存(针对的是 SqlSession会话)和二级缓存(针对的是 Mapper)中,此时,如果当前会话关闭了,那么这个会话的一级缓存就没有了,这个时候可以从二级缓存中获取数据。

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

12 说一说 MyBatis 的一级缓存

与数据库同一次会话期间查询到的数据会放在一级缓存中,以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库。

一级缓存失效的四种情况:

  1. 当 SqlSession 相同,两次查询之间执行了增删改操作时,一级缓存会失效。因为对于增删改操作,即使是操作与原来查询不同的元素,依然会刷新缓存;

  2. SqlSession 相同,但查询不同的东西,即查询条件不同;

  3. SqlSession 不同时,每个 SqlSession 中的缓存相互独立;

  4. SqlSession 相同,手动清除一级缓存。

13 说一说 MyBatis 的二级缓存
为什么需要二级缓存呢,因为一级缓存当会话关闭后就会释放,所以我们需要一个这个情况下数据依然存在的缓存。
只要开启了二级缓存,我们在同一个 Mapper 中的查询,可以在二级缓存中拿到数据。不过查出的数据都会被默认先放在一级缓存中,只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中。

Spring、MyBatis 面试题,清华大学出版社java基础入门课后题相关推荐

  1. java基础入门课后习题_《Java基础入门》课后习题及答案

    <Java基础入门>课后习题及答案Java基础入门,课后习题,答案 博学谷--让IT教学更简单,让IT学习更有效 <Java基础入门>课后习题 第1章Java开发入门 一.填空 ...

  2. JAVA基础入门编程题练习(一)

    JAVA基础入门编程题练习(一) 1.设计一个学生类Student和它的一个子类Undergraduate.要求如下: (1) Student类有name和age属性,一个包含两个参数的构造方法,用于 ...

  3. java基础入门课后习题答案_《Java基础入门》课后习题及答案

    <Java基础入门>课后习题及答案Java基础入门,课后习题,答案 博学谷--让IT教学更简单,让IT学习更有效 第6章JavaAPI 一.填空题 1.在Java中定义了两个类来封装对字符 ...

  4. java基础入门课后答案黑马程序员

    前言 最近刷到了一句耐人寻味的话,"解决雪崩问题的最好办法是不发生雪崩". 不论是在硅谷互联网公司里还是在国内的互联网平台上,曾多次遇到过海量规模的交易瞬间吞噬平台的悲惨故事. 核 ...

  5. 帮你快速拿Offer!java基础入门课后答案第二版

    一面(技术面:算法+Redis+MySQL+网络) 给定m个不重复的字符 [a, b, c, d],以及一个长度为n的字符串tbcacbdata,问能否在这个字符串中找到一个长度为m的连续子串,使得这 ...

  6. Java基础入门:IDEA软件安装和软件初始化设置

    IDEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量. 它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公司中,使用的就是I ...

  7. Java 基础入门,小白提升路线图

    1000+最新Java面试题 获取学习路线资料啦 Java的基础知识就像我们所住的房子的地基,如果地基不稳,上面所盖的楼房再宏伟,也是没人敢去入住的,同理Java的基础不牢固,以后也很难成为真正意义上 ...

  8. java基础入门-01-【基础、运算符、判断和循环、数组、方法】

    Java基础入门-01-[基础.运算符.判断和循环.数组.方法] Java入门到起飞(含斯坦福大学练习题+力扣算法题+大厂java面试题) 1.Java入门 常用CMD命令 Java基础学习 JDK的 ...

  9. Java基础入门-详细总结

    Java基础入门知识总结 一.java基础 1.1 java基础知识 1.2java的基本数据类型 1.3运算符 1.4循环结构 1.5数组 二.面向对象 2.1方法 2.2面向对象 2.3内存管理 ...

  10. 叮!您收到一份超值Java基础入门资料!

    摘要:Java语言有什么特点?如何最大效率的学习?深浅拷贝到底有何区别?阿里巴巴高级开发工程师为大家带来Java系统解读,带你掌握Java技术要领,突破重点难点,入门面向对象编程,以详细示例带领大家J ...

最新文章

  1. linux回调函数的使用
  2. Wannafly挑战赛9
  3. python写入数据到excel中_Python写入数据到Excel
  4. ACM Computing Surveys 2021:基于会话推荐系统的最新长文综述
  5. 课程《设计模式之美》笔记之关于java四大特性
  6. fortran语言和python_fortran是什么语言吗?
  7. SQL Server 2008空间数据应用系列十一:提取MapInfo地图数据中的空间数据解决方案...
  8. 关于SAS学习的记录
  9. 域计算机策略软件安装方法,windows域软件下发策略
  10. 小白学统计|面板数据分析与Stata应用笔记(一)
  11. C++经典编程题目(九)玩火柴棍游戏
  12. CentOS7下安装jmeter5.3
  13. 计算机开机定屏,电脑主板开机画面定屏解决方法
  14. 战地一服务器性能低怎么办,《战地1》帧数优化图文攻略 战地1帧数低怎么办?...
  15. [源码和文档分享]基于QT实现的联网国际跳棋游戏
  16. 自旋锁与互斥锁的对比、手工实现自旋锁
  17. (jetson nano)ubuntu安装vscode为ros编写提供开发环境
  18. 复制百度文库的文字加什么后缀_10种方式教你复制网页中不能复制的文字
  19. linux les命令,如何使用LES对Linux进行渗透测试研究
  20. stm32-IAP(在线升级程序)

热门文章

  1. 目标检测(三)——Two-Stage——Faster R-CNN
  2. 计算机会计期末考试试题题量及构成,2016年《会计电算化》考试真题及答案
  3. 实验报告一 网络侦查与网络扫描
  4. C++学习 day3
  5. 掉头发第一步之python正则表达式之re模块
  6. 如何告别职场菜鸟,成为职场“老司机”!
  7. python windows和linux路径_获取windows和linux下U盘路径
  8. 毕业一周年,你还好吗?
  9. pygame图像连续旋转
  10. 树莓派开发之旅 (十二)【树莓派常见疑难杂症】