Spring

1 Spring 框架中的单例bean是线程安全的吗?

不是线程安全的

Spring框架中有一个@Scope注解,默认的值是singleton,单例的

因为一般在spring的bean的中都是注入无状态的对象,没有线程安全的问题。如果在bean中定义了可修改的成员变量,是要考虑到线程安全的问题,可以使用多例或者加锁来解决。

2 什么是AOP?

AOP 称为面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”( Aspect ),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。

使用场景:

  1. 记录操作日志
  2. 缓存处理
  3. spring中内置的事务处理

2.1 Spring中的事务是如何实现的?

Spring支持编程式事务管理和声明式事务管理两种方式:

  1. 编程式事务控制:需使用Transaction Template来进行实现,对业务的代码又倾入性,项目很少使用
  2. 声明式事务管理:声明式事务管理建立再AOP之上的,其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编制到拦截的方法中,也就是再目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

3 Spring中事务失效的场景有哪些?

  1. 异常捕获处理
  2. 抛出检查异常
  3. 非public方法

情况一:异常捕获处理

image

进行了try catch会直接抛出异常,导致结果不对。

原因:

事务通知只会捉到目标抛出的异常,才能进行后续的回滚处理,如果目标自己处理掉了异常,事务将无法进行回滚

解决:

在catch块中自己抛出异常,throw new RuntimeException()

情况二:抛出检查异常

image

读取文件不存在,没办法进行回滚

原因:

Spring只进行回滚非检查异常

解决:

配置rollbackFor属性,@Transactional(rollbackFor=Exception.class)

情况三:非 public 方法导致的事务失效

image

原因:

Spring为方法创建代理、添加事务通知、前提条件都是该方法的public的

解决:

改为public方法

4 Spring 的bean 的生命周期?

BeanDefinition

Spring容器在进行实例化时,会将xml配置的<bean> 的信息封装成一个Bean Definition对象,Spring根据BeanDefinition来创建Bean对象,里面有很多的属性用来描述Bean。

image

image

5 Spring中的循环引用?

多个对象互相使用

image

5.1 三级缓存解决循环依赖

缓存名称 源码名称 作用
一级缓存 singletonObjects 单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象
二级缓存 earlySingletonObjects 缓存早期的bean对象(生命周期还没有走完)
三级缓存 singletonFactories 缓存的时ObjectFactory,表示对象工厂,用来创建某个对象的

一级缓存的作用: 限制 bean 在 beanFactory 中只存一份,即实现 singleton scope ,解决不了循环依赖

image

如果要想打破循环依赖,就需要一个中间人的参与,这个中间人就是二级缓存

image

三级缓存

image

构造方法出现的循环依赖三级缓存无法解决。

解决方法:

添加注解@Lazy

6 SpringMVC的执行流程?

  1. 试图阶段(老旧JSP)
  2. 前后端分离

视图阶段(JSP)

image

前后端分离阶段(接口开发,异步请求)

image

7 SpringBoot的自动配置原理

image

8 Spring框架的常见注解(Spring,SpringBoot,SpringMVC)

Spring注解

|注解|说明||
|@Component、@Controller、@Service、@Respository|使用类上用于实例化Bean||
|@Autowired|使用在字段上用于根据类型依赖注入||

@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Scope 标注Bean的作用范围
@Configure 指定当前类是一个spring配置类,当创建容器时会从该类上加载注解
@ComponentsScan 用于指定spring在初始化容器上要扫描的包
@Bean 使用在方法上,标注将该方法的返回值存储到Spring容器中
@Import 使用@Import导入的类会被Spring加载到IOC容器中
@Aspect、@Before、@After、@Around、@Pointcut 用于切面编程

SpringMVC相关注解:

|注解|说明||
|@RequestMapping|用于映射请求路径,可以定义在类上和方法上。用于类上,则表示类中的所有的方法都是以该地址作为父路径||
|@RequestBody|注解实现接收 http 请求的 json 数据,将 json 转换为 java 对象||

@RequestParam 指定请求参数的名称
@PathViriable 从请求路径下中获取请求参数 (/user/{id}) ,传递给方法的形式参数
@ResponseBody 注解实现将 controller 方法返回对象转化为 json 对象响应给客户端
@RequestHeader 获取指定的请求头数据
@RestController @Controller + @ResponseBody

9 MyBatisz的执行流程?

image

10 Mybatis是否支持延迟加载?

Mybatis支持延迟加载,但是默认没有开启

image

延迟加载的原理:

  1. 使用CGLIB创建目标对象的代理对象
  2. 当调用目标方法user.getOrderList()时,进入拦截器invoke方法,发现user.getOrderList()时null值,执行sql查询order列表
  3. 把order查询上来,然后调用user.setOrderList(List orderList),接着完成user.getOrderList()方法的调用

image

10 Mybatis的一级、二级缓存用过吗?

一级缓存

基于PerpetualCache的HashMap本地缓存,其储存作用域为session,当session进行flush或者close之后,该session中的所有的cache就将清空,默认打开一级缓存

二级缓存

是基于namespace和mapper的作用域起作用,不是依赖于SQL session,默认采用PerpetualCache HashMap存储

注意事项:

  1. 对于缓存数据更新机制,当某一个作用域(一级缓存session/二级缓存Namespace)的进行了新增、修改、删除操作后,默认该作用域下所有的select中的缓存将被clear
  2. 二级缓存需要缓存的数据实现Serializable接口
  3. 只有会话提交或者关闭之后,一级缓存中的数据才会转移到二级缓存中