• SSM框架17问--面试必备


    1、什么是spring-IOC和DI

    可以简单的理解为springIoc和DI都是一种思想,而DI是springIoc的具体实现。以往我们创建对象都需要通过new关键字进行对象的创建,随着对象的依赖关系逐渐复杂,new的方式让代码显得更加繁琐。而springIoc(控制反转)的出现可以让开发者只关注代码逻辑的开发,而将所有的对象统一交给Spring容器进行管理,而spring容器管理对象的方式就是通过DI达到的,DI(依赖注入)的方式有三种:Setter、构造方法、接口;具体实现可参照:Spring-Ioc-DI的三种注入方式:_暇光署墨的博客-CSDN博客_spring ioc注入的三种方式

    2、spring支持的几种bean的作用域

    • singleton:使用该属性定义bean时,IOC容器仅创建一个Bean实例,IOC容器每次返回的是同一个Bean实例
    • prototype:使用该属性定义bean时,IOC容器可以创建多个Bean实例,每次返回都是一个新的Bean实例
    • request:该属性仅对http请求产生作用,使用该属性定义Bean时,每次HTTP请求都会创建一个新的Bean,使用WebApplicationContext环境
    • session:该属性仅使用于HTTP session,同一个session共享一个Bean实例,不同的session使用不同的实例
    • global-session:该属性仅使用于HTTP session,同session不同的是,不同的session共享同一个实例

    3、spring框架中的单例bean是线程安全的吗 

    spring的Bean默认是单例模式的,单例bean是指IOC容器中就只有这么一个bean,是全局共享的,有多少个线程来访问用的都是这个bean。由于框架并没有对bean进行多线程的封装处理,所以单例模式的bean不是线程安全的;最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的
    安全了。

    4、 spring自动装配的Bean有哪些方式?

    spring 配置文件中 节点的 autowire 参数可以控制 bean 自动装配的方式:

    • default - 默认的方式和 “no” 方式一样
    • no - 不自动装配,需要使用 节点或参数
    • byName - 根据名称进行装配
    • byType - 根据类型进行装配
    • constructor - 根据构造函数进行装配

    5、JDK动态代理和CGLIB动态代理区别 

    JDK动态代理的实现是通过被代理对象实现的接口产生其代理对象的;带定义getProxy()方法的时候通过类加载器获取被代理对象实现的接口,通过被代理对象的类加载器以及实现的接口创建并返回代理对象。

    CGLIB动态代理是通过创建被代理对象的子类来创建代理对象的;在定义getProxy()方法的时候,代理对象是通过创建并代理的子类来创建的,使用Enhancer来创建对象,并制定父类,并进行setCallBack进行回调,使用create()创建并返回getProxy。

    spring底层会根据类是否实现接口来进行判断,是使用jdk还是cglib。

    6、什么是AOP?你们项目中有没有使用到AOP

    AOP(面向切面编程),是一种“横切”的技术(底层实现是动态代理),对原油的业务逻辑进行拦截,并对原有的业务逻辑进行增强,在不改变原有业务的情况下对业务逻辑进行增强。有几个名词专有名词要注意:

    JoinPoint-连接点:在应用执行过程中能够插入切面(Aspect)的一个点

    Pointcut-切入点:实际被增强的方法,就是切入点,比如说有俩方法,一个方法被增强了一个没被增强,则被增强的方法叫做切入点,没被增强的方法就不能叫做切入点

    通知/增强:真正被增强的逻辑部分称为通知

    切点:添加到切入点的新增的业务方法

    切面:定义切点方法的类

    使用场景:异常处理、事务提交/回滚、检验是否登陆

    7、SpringMvc执行流程

     

    1、前端发送请求被前端控制器DispatcherServlet拦截

    2、前端控制器调用处理器映射HandlerMapping对请求URL进行解析,解析之后返回给前端控制器

    3、前端控制器调用处理器适配器处理调用链

    4、处理器适配器基于反射通过适配器设计模式完成处理器(控制器)的调用,处理用户请求

    5、处理器适配器将控制器返回的视图和数据信息封装成ModelAndVIew响应给前端控制器

    6、前端控制器调用视图解析器ViewResolve对ModelAndView进行解析,将解析结果(视图资源和数据)响应给前端控制器

    7、前端控制器调用视图view组件将数据进行渲染,将渲染的结果(静态资源)响应给前端控制器

    8、前端控制器响应用户请求

    9、mybatis #{}和${}的区别

    #{}:

            (1)、编译好SQL后语句再去取值

            (2)、将传入的数据都当成一个字符串,会对传入的变量自动加一个单引号。如:user_id = #{userId},如果传入的值是111,那么解析成sql时的值为user_id = ‘111’,如果传入的值是id,则解析成的sql为user_id = ‘id’。

            (3)、参数占位符,即预编译

    ${}:

         (1)取值以后再去编译SQL语句

         (2)将传入的参数直接显示生成在sql中,且不加任何引号。如:user_id = ${userId},如果传入的值是111,那么解析成sql时的值为user_id = 111 , 如果传入的值是id,则解析成的sql为user_id = id。

         (3)字符串替换符,即SQL拼接

    10、Mybatis如何获取生成的主键 

    自增主键:

     第一种方式是使用useGeneratedKeys + keyProperty组合的方式,其中userGeneratedKeys代表是告诉mybatis要使用自增生成的主键,keyProperty是告诉mybatis主键字段是哪个,如下:

    1. "insert" parameterType="Person" useGeneratedKeys="true" keyProperty="id">
    2. INSERT INTO person(name, pswd)
    3. VALUE (#{name}, #{pswd})

    第二种方式是通过来指定sql语句获取生成的主键ID,如下:

    1. "insert" parameterType="Person">
    2. "id" resultType="long" order="AFTER">
    3. SELECT LAST_INSERT_ID()
    4. INSERT INTO person(name, pswd)
    5. VALUE (#{name}, #{pswd})

    11、当实体类中的属性名和表中的字段名不一样怎么办 ?

     第 1 种: 通过在查询的 sql 语句中定义字段名的别名,让字段名的别名和实体类 的属性名一致。

    第 2 种: 通过来映射字段名和实体类属性名的一一对应的关系。

    1. <result property = “orderno” column =”order_no”/>

    12、mybatis如何实现多表查询 

    在实体类中加入对应的关联查询的字段或集合;

    (1)、一对多的关系映射使用的是collection

    (2)、一对一的关系映射使用的是association

     13、mybatis都有哪些动态sql?能简述一下动态SQL的执行原理嘛?

    1、Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。

    2、Mybatis 提 供 了 9 种 动 态 sql 标 签 : trim|where|set|foreach|if|choose|when|otherwise|bind。

    3、其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。
     

     14、mybatis是否支持延迟加载?

     (1)支持!MyBatis 有两种加载方式:立即加载和延迟加载

    MyBatis 只支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的是一对一关联查询的,collection 指的是一对多关联查询。

    (2)在 MyBatis 配置文件中,有两种方式可以配置是否启用延迟加载:

    第一种是在配置文件的 标签中为所有嵌套查询设为延迟加载

    第二种是在 中添加 < fetchType > 设置

    1. "lazyLoadingEnabled" value="true"/>
    2. "lazyLoadTriggerMethods" value=""/>

    (3)一般情况下,一对多查询使用延迟加载一对一查询使用立即加载。因为一对多可能有上万甚至更多的数据,如果立即加载的话会很占用空间,所以使用延迟加载;而一对一查询的话,只有一条数据,立即加载也不会有什么影响,所以可以立即加载。

    15、如何使用mybatis实现批量插入? 

    使用Mybatis框架批量插入的3种方法:多次调用insert方法、foreach标签、batch模式

     16、mybatis批量插入能否返回主键?

    Mybatis在插入单条数据的时候有两种方式返回自增主键:

     

    1、对于支持生成自增主键的数据库:增加 useGenerateKeys和keyProperty ,标签属性。  

    2、不支持生成自增主键的数据库:使用标签。 

    17、mybatis的一级、二级缓存

    一级缓存为 ​sqlsesson​ 缓存,缓存的数据只在 SqlSession 内有效。在操作数据库的时候需要先创建 SqlSession 会话对象,在对象中有一个 HashMap 用于存储缓存数据,此 HashMap 是当前会话对象私有的,别的 SqlSession 会话对象无法访问。
     

    二级缓存是​ mapper​ 级别的缓存,也就是同一个 namespace 的 mapper.xml ,当多个 SqlSession 使用同一个 Mapper 操作数据库的时候,得到的数据会缓存在同一个二级缓存区域

    二级缓存默认是没有开启的。需要在 setting 全局参数中配置开启二级缓存

    开启二级缓存步骤:

    1、​conf.xml​ 配置全局变量开启二级缓存
     

    1. "cacheEnabled" value="true"/>默认是false:关闭二级缓存
  • 相关阅读:
    webpack5基于React+Antd搭建开发和生产环境
    电脑重装系统后如何删除微软商店下载记录
    如何看待智慧城市建设中的改变和机遇?
    docker (八)-dockerfile制作镜像
    驱动 | Linux | NVMe - 1. 内核驱动
    Android Studio一直出现这个问题,尝试了很多方法都无法解决
    GoLong的学习之路(十)语法之函数
    93.(后端)分类参数增加接口实现——flask框架使用蓝图与restful发送请求添加数据
    【动手学深度学习-Pytorch版】注意力汇聚:Nadaraya-Watson 核回归
    Kitchen Racks
  • 原文地址:https://blog.csdn.net/weixin_45295447/article/details/127713224