SSM常见面试

  1. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
  2. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
  3. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
  4. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
  5. Handler让具体的Controller执行。
  6. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
  7. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
  8. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
  9. 视图解析器将解析的逻辑视图名传给DispatcherServlet。
  10. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
  11. 最终视图呈现给用户。

12、 @Component和@Bean的区别是什么

1.作用对象不同。@Component注解作用于类,而@Bean注解作用于方法。

2.@Component注解通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径)。@Bean注解通常是在标有该注解的方法中定义产生这个bean,告诉Spring这是某个类的实例,当我需要用它的时候还给我。

3.@Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册bean。比如当引用第三方库的类需要装配到Spring容器的时候,就只能通过@Bean注解来实现。

13、将一个类声明为Spring的bean的注解有哪些?

我们一般使用@Autowired注解去自动装配bean。而想要把一个类标识为可以用@Autowired注解自动装配的bean,可以采用以下的注解实现:

1.@Component注解。通用的注解,可标注任意类为Spring组件。如果一个Bean不知道属于哪一个层,可以使用@Component注解标注。

2.@Repository注解。对应持久层,即Dao层,主要用于数据库相关操作。

3.@Service注解。对应服务层,即Service层,主要涉及一些复杂的逻辑,需要用到Dao层(注入)。

4.@Controller注解。对应Spring MVC的控制层,即Controller层,主要用于接受用户请求并调用Service层的方法返回数据给前端页面。

14、#{}和${}的区别是什么?

两者在 MyBatis 中都可以作为 SQL 的参数占位符,在处理方式上不同

  • #{}:在解析 SQL 的时候会将其替换成 ? 占位符,然后通过 JDBC 的 PreparedStatement 对象添加参数值,这里会进行 预编译处理,可以有效的防止 SQL 注入,提高系统的安全性
  • ${}:在 MyBatis 中带有该占位符的 SQL 片段会被解析成动态 SQL 语句,根据入参直接替换掉这个值,然后执行数据库相关操作,存在 SQL注入 的安全性问题

15、最佳实践中,通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗

Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个、

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。

Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

16、MyBatis的实现逻辑

  1. 在 MyBatis 的初始化过程中,会生成一个 Configuration 全局配置对象,里面包含了所有初始化过程中生成对象
  2. 根据 Configuration 创建一个 SqlSessionFactory 对象,用于创建 SqlSession “会话”
  3. 通过 SqlSession 可以获取到 Mapper 接口对应的动态代理对象,去执行数据库的相关操作
  4. 动态代理对象执行数据库的操作,由 SqlSession 执行相应的方法,在他的内部调用 Executor 执行器去执行数据库的相关操作
  5. 在 Executor 执行器中,会进行相应的处理,将数据库执行结果返回

17、MyBatis的缓存实现逻辑

MyBatis 提供了一级缓存和二级缓存

在 MyBatis 的开启一个 SqlSession 会话时,都会创建一个 Executor 执行器对象

  • 一级缓存 在 Executor 执行器(SimpleExecutor)中有一个 Cache 对象中,默认就是一个 HashMap 存储缓存数据,执行数据库查询操作前,如果在一级缓存中有对应的缓存数据,则直接返回,不会去访问数据库 默认的缓存区域为 SESSION,表示开启一级缓存,可以设置为 STATEMENT,执行完查询后会清空一级缓存,所有的数据库更新操作也会清空一级缓存 缺陷:在多个 SqlSession 会话时,可能导致数据的不一致性,某一个 SqlSession 更新了数据而其他 SqlSession 无法获取到更新后的数据,出现数据不一致性,这种情况是不允许出现了,所以我们通常选择 “关闭”一级缓存
  • *二级缓存

在 Executor 执行器(CachingExecutor)中有一个 TransactionalCacheManager 对象中,可以在一定程度上解决的一级缓存中多个 SqlSession 会话可能会导致数据不一致的问题,就是将一个 XML 映射文件中定义的缓存对象放在全局对象中,对于同一个 Mapper 接口都是使用这个 Cache 对象,不管哪个 SqlSession 都是使用该 Cache 对象

执行数据库查询操作前,如果在二级缓存中有对应的缓存数据,则直接返回,没有的话则去一级缓存中获取,如果有对应的缓存数据,则直接返回,不会去访问数据库

默认全局开启,需要在每个 XML 映射文件中定义

缺陷:对于不同的 XML 映射文件,如果某个的 XML 映射文件修改了相应的数据,其他的 XML 映射文件获取到的缓存数据就可能不是最新的,也出现了脏读的问题,当然你可以所有的 XML 映射文件都通过 <cache-ref></cache-ref>来使用同一个 Cache 对象,不过这样太局限了,且缓存的数据仅仅是保存在了本地内存中,对于当前高并发的环境下是无法满足要求的,所以我们通常不使用MyBatis的缓存

SSM常见面试

18、Mybatis是如何进行分页的?

Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的 内存分页,而非 数据库分页

所以,实际场景下,不适合直接使用 MyBatis 原有的 RowBounds 对象进行分页。而是使用如下两种方案:

  • 在 SQL 内直接书写带有数据库分页的参数来完成数据库分页功能
  • 也可以使用分页插件来完成数据库分页。

这两者都是基于数据库分页,差别在于前者是工程师 手动编写分页条件,后者是插件 自动添加分页条件。

分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义分页插件。在插件的拦截方法内,拦截待执行的 SQL ,然后重写 SQL ,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。

举例: SELECT * FROM student ,拦截 SQL 后重写为: select * FROM student LIMI 0&#xFF0C;10

目前市面上目前使用比较广泛的 MyBatis 分页插件有:

Original: https://www.cnblogs.com/peixinyu/p/16372315.html
Author: xy-pei
Title: SSM常见面试

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/593092/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球