Spring连环问

160 阅读7分钟

Spring基础

1、Spring框架了解吗?说说它的优缺点

Spring是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。

一般说Spring框架指的都是Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:Core Container 中的Core组件是Spring所有组件的核心,Beans组件和Context组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。

image.png

Spring官网列出的Spring的6个特征:

  • 核心技术:依赖注入(DI),AOP,事件(events),资源,i18n,验证,数据绑定,类型转换,SpEL。
  • 测试:模拟对象,TestContext框架,Spring MVC测试,WebTestClient。
  • 数据访问:事务,DAO支持,JDBC,ORM,编组XML。
  • Web支持:Spring MVC和Spring WebFlux Web框架。
  • 集成:远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存。
  • 语言:Kotlin,Groovy,动态语言。

Spring框架的好处?

  • 轻量级:Spring框架是轻量级的,最基础的版本大约只有2MB
  • 控制反转(IOC):通过控制反转技术,实现了解耦合。对象给出它们的依赖,而不是创建或查找依赖的对象。
  • 面向切面(AOP):Spring支持面向切面的编程,并将应用程序业务逻辑与系统服务分离。
  • MVC框架:Spring的WEB框架是一个设计良好的web MVC框架,它为web框架提供了一个很棒的替代方案。
  • 容器:Spring包含并管理对象的生命周期和配置。
  • 事务管理:Spring提供了一个一致性的事务管理接口,可以收缩到本地事务,也可以扩展到全局事务(JTA)。
  • 异常处理:Spring提供了方便的API来将具体技术的异常(由JDBC、Hibernate或JDO抛出)转换为一致的unchecked异常。

Spring框架的缺点?

使用了大量的反射机制,反射机制非常占用内存

  1. 重量级框架

我们看到Spring架构图时会发现Spring里面包含有很多其他组件,比如数据访问、MVC、事务管理、面向切点、WebSocket功能等,因此这么复杂的组件集中到一起就会提高初学者的学习成本。还有一方面随着你的服务越多,那么Spring的启动就会变得越慢

  1. 集成复杂

比如我们想要使用MyBatis或者MongoDB的时候,我们要做很多工作不管使用配置方式也好还是使用注解方式。

  1. 配置复杂

在使用Spring的时候,我们更多可能是选择XML进行配置,但目前这种配置方式已不再流行。

  1. 构建和部署复杂

启动Spring的IOC容器,是完全要依赖于第三方的web服务器。自身不能启动的。

2、Spring,Spring MVC,Spring Boot 之间什么关系?

Spring MVC 是 Spring 中的一个很重要的模块,主要赋予 Spring 快速构建 MVC 架构的 Web 程序的能力。MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。

Spring Boot 旨在简化 Spring 开发(减少配置文件,开箱即用!)。

Spring Boot 只是简化了配置,如果你需要构建 MVC 架构的 Web 程序,你还是需要使用 Spring MVC 作为 MVC 框架,只是说 Spring Boot 帮你简化了 Spring MVC 的很多配置,真正做到开箱即用!

Spring IoC、AOP

详见:Spring IoC、AOP - 掘金 (juejin.cn)

Spring MVC

详见:Spring MVC - 掘金 (juejin.cn)

Spring事务

1、Spring管理事务的方式有几种?

  • 编程式事务:在代码中硬编码(不推荐使用) : 通过 TransactionTemplate或者 TransactionManager 手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。
  • 声明式事务:在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)

2、Spring 事务中哪几种事务传播行为?

事务传播行为是为了解决业务层方法之间互相调用的事务问题

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

正确的事务传播行为可能的值如下:

1.TransactionDefinition.PROPAGATION_REQUIRED

使用的最多的一个事务传播行为,我们平时经常使用的@Transactional注解默认使用就是这个事务传播行为。如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

2.TransactionDefinition.PROPAGATION_REQUIRES_NEW

创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。

3.TransactionDefinition.PROPAGATION_NESTED

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

4.TransactionDefinition.PROPAGATION_MANDATORY

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

这个使用的很少。

若是错误的配置以下 3 种事务传播行为,事务将不会发生回滚:

  • TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。

3、Spring 事务中的隔离级别有哪几种?

和事务传播行为这块一样,为了方便使用,Spring 也相应地定义了一个枚举类:Isolation

public enum Isolation {

    DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),

    READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),

    READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),

    REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),

    SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);

    private final int value;

    Isolation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }

}

下面我依次对每一种事务隔离级别进行介绍:

  • 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、@Transactional(rollbackFor = Exception.class)注解了解吗?

Exception 分为运行时异常 RuntimeException 和非运行时异常。事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。

@Transactional 注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

@Transactional 注解中如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,加上 rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚。

转载自:Spring常见面试题总结 | JavaGuide

Spring Security