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主键字段是哪个,如下:

<insert id="insert" parameterType="Person" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO person(name, pswd)
    VALUE (#{name}, #{pswd})
</insert>

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

<insert id="insert" parameterType="Person">
    <selectKey keyProperty="id" resultType="long" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
        
    INSERT INTO person(name, pswd)
    VALUE (#{name}, #{pswd})
</insert>

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

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

<select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>
	select order_id id, order_no orderno ,order_price price form
	orders where order_id=#{id};
</select>

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

<select id="getOrder" parameterType="int" resultMap="orderresultmap">
	select * from orders where order_id=#{id}
</select>
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
	<!–用 id 属性来映射主键字段–>
	<id property=”id” column=”order_id”>
	<!–用 result 属性来映射非主键字段,property 为实体类属性名,column为数据表中的属性–>
	<result property = “orderno” column =”order_no”/>
	<result property=”price” column=”order_price” />
</reslutMap>

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 配置文件中,有两种方式可以配置是否启用延迟加载:

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

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

<settings>
        <!--2.开启延迟加载-->
        <!--(1)此方式为:设置所有的分解式(N+1)查询都为延迟加载:
      注意:这种方式很少使用,因为不可能为所以分解式查询都设置为延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--(2)此方式为:映射文件中<collection>或<association>中设置了fetchType的方法触发延迟加载,设置为空字符串即可。-->
        <setting name="lazyLoadTriggerMethods" value=""/>
    </settings>

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

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

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

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

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

 

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

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

17、mybatis的一级、二级缓存

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

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

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

开启二级缓存步骤:

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

<settings>
    <setting name="cacheEnabled" value="true"/>默认是false:关闭二级缓存
<settings>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暇光曙墨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值