Spring框架


1. 什么是Spring框架?

Spring是一个轻量型的开发框架,旨在提高开发人员的开发效率和系统的可维护性

Spring的6个特征:

  • 核心技术
  • 测试
  • Web支持
  • 集成
  • 语言

1.1 列举一些重要的Spring模块

  • Spring Core:基础,Spring其他所有的功能都需要依赖该类库,主要提供IOC依赖注入功能
  • Spring Aspects:该模块为与AspectJ的集成提供支持
  • Spring Aop:提供了面向切面的编程实现
  • Spring JMS:Java消息服务
  • Spring ORM: 用于支持Hibernate等ORM工具
  • Spring Web:为创建Web应用程序提供支持
  • Spring Test:提供了对JUnit和TestNg测试的支持

1.3 @RestController 和@Controller

@Controller 返回的是一个视图

@RestController = @ResponseBody + @Controller 返回JSON或者XML形式数据

(返回对象,对象数据以xml或者JSON的格式写入到HTTP响应(Response)中)

@ResponseBody 注解的作用是将 @Controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到HTTP 响应(Response)对象的 body 中,通常用来返回 JSON 或者 XML 数据,返回 JSON 数据的情况比较多。

1.4 Spring IOC&AOP

IOC:它是一种设计思想,将程序中手动创建对象的控制权移交给Spring框架来管理。IOC容器是Spring用来实现IOC的载体,IOC容器实际上就是个Map(Key,value),Map中存放的是各种对象。

将对象之间的相互依赖关系交给IOC容器来管理,由IOC容器来完成对象的注入。IOC容器就像一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的

Spring IOC的初始化过程:

SpringIOC初始化过程

IOC的依赖倒置:

倒置前

转变——–>

倒置后

1.5 SpringAOP和AspectJAOP区别?

SpringAOP是运行时增强,AspectJAOP是编译时增强,前者基于代理,后者基于字节码操作;

1.6 Spring中的Bean的作用域有哪些?

  • Singleton:唯一的Bean实例,Spring默认bean都是单例的
  • prototype:每次请求都会创建一个新的实例
  • request:每一次HTTP请求都会产生一个新的Bean,该Bean仅在当前HTTP request内有效
  • session:每一次HTTP请求都会产生一个新的Bean,该Bean仅在当前HTTP session内有效
  • global-session:与session不同的是,所有的session共享一个session Bean,Spring5已经移除

Spring创建Bean的时候如果没有配置作用域,默认是Singleton作用域

123

1.7 Spring中的单例Bean的线程安全问题了解吗?

当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题

解决方式:

  1. 在Bean对象中避免定义可变的成员变量(不现实)
  2. 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中

注:ThreadLocal 中文较为准确的叫法为 线程局部变量

1.8 @Component 和 @Bean 区别?

  1. 作用对象不同 @Component 注解用于类,@Bean注解用于方法
  2. @Component通常是通过类路径扫描自动侦测装配到Spring容器当中(@ComponentScan注解定义要扫描的路径)。@Bean注解通常是我们在标有该注解的方法中定义产生这个bean,@Bean会告诉Spring这是某个类的示例,当我需要的时候还给我;
  3. @Bean注解比@Component注解的自定义性更强,更灵活,很多地方我们只能通过@Bean来注册Bean。例如我们引用第三方库中的类需要装配到Spring容器的时候,这时候只能通过@Bena来完成

1.9 将一个类声明为Spring的Bean的注解有哪几个?

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

  • @Component
  • @Service
  • @Controller
  • @Repository

2.0 Spring中的Bean的生命周期?

  • Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
  • Bean实例化后对将Bean的引入和值注入到Bean的属性中
  • 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
  • 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
  • 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
  • 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
  • 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
  • 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
  • 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
  • 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

2.1 谈谈对Spring MVC的了解?

简单原理图:简单原理图

用户发起请求,前端控制器接收数据并拦截请求,调用service层,service调用dao层返回处理结果,控制器接收结果返回,通过视图渲染返回视图

2.2 Spring MVC工作原理?

工作原理

  1. 客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
  2. DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
  3. 解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。
  4. HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑。
  5. 处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
  6. ViewResolver 会根据逻辑 View 查找实际的 View。
  7. DispaterServlet 把返回的 Model 传给 View(视图渲染)。
  8. 把 View 返回给请求者(浏览器)

2.2 Spring框架中用到了哪几个设计模式?

  • 工厂设计模式:Spring工厂模式 通过 BeanFactoryApplicationContext创建Bean对象
  • 单例设计模式:Spring中 Bean默认都是单例
  • 代理设计模式:Spring中AOP功能的实现
  • 包装器设计模式:项目需要连接多个数据库,可以根据用户需求动态切换不同的数据源
  • 适配器模式:Spring AOP的增强或者通知使用到了适配器模式,SpringMVC也使用到了,适配Controller;
  • 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用

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

  • 编程式事务:在代码中硬编码
  • 声明式事务:在配置文件中配置

声明式事务分为两种:

  1. 基于XML的声明式事务
  2. 基于注解的声明式事务

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

和MySQL事务隔离级别类似,但多了一个默认的隔离级别

  • 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的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别

2.5@Transactional(rollbackFor = Exception.class)注解了解吗?

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

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

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

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

  • 支持当前事务:
    • TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
    • TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
    • TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
  • 不支持当前事务
    • TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
    • TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
    • TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
  • 其他情况
    • TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

文章作者: Z.Wfeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Z.Wfeng !
  目录