Spring基础


介绍

多模块集合,Spring Framework

  • 简化开发,解耦,集成其他框架
  • 低侵入式设计
  • aop与di
  • 支持声明式事务

Spring模块

  • Spring Core:基础,主要提供IOC依赖注入功能
  • Spring AOP :提供了面向切面的编程实现。
  • Spring JDBC : Java数据库连接。
  • Spring JMS :Java消息服务。
  • Spring ORM : 用于支持Hibernate等ORM工具。
  • Spring Web : 为创建Web应用程序提供支持。
  • Spring Test : 提供了对 JUnit 和 TestNG 测试的支持。

@RestController 与 @Controller

  • @Controller不加@ResponseBody属于传统的Spring MVC应用,返回的是一个试图 @Controller加@ResponseBody返回JSON或XML形式数据,相当于@Controller+@ResponseBody=RestController

    @ResponseBody注解是将Controller方法反悔的对象转为指定的格式后,写入HTTP对象的body中,一般返回Json

  • @RestController返回Json或XML数据 @RestController值返回对象,对象以Json或XML形式写入HTTP响应中,属于RESTful Web服务

IOC与AOP

IOC

是一种设计思想,将原本程序中手动创建对象的控制权,交由Spring框架管理。IOC实际上是一个MAP(key,value),Map存放的是各种对象。

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

初始化过程

  1. XML读取
  2. resource解析
  3. BeanDefinition注册
  4. BeanFactory(它负责生产和管理各个 bean 实例)

AOP

面向切面编程,能够将与业务无关,却为业务模块共同调用的逻辑或责任,比如日志,事务等封装起来,减少系统的重复代码,降低模块之间的耦合度,有利于未来的扩展性。

基于动态代理

  • JDK:如果要代理的对象,实现了某个街口,就会使用JDK创建代理对象,通过反射
  • Cglib:没有实现接口的对象,使用Cglib生成一个被代理对象的子类作为代理

Spring bean

bean的作用域

  • singleton:唯一bean实例,Spring bean默认都是单例的
  • prototype:每次请求都会生一个新的bean实例
  • request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
  • session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。
  • global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义

Spring中的单例bean的线程安全问题

单例bean的存在主要是因为多线程操作同一个对象的时候,对这个对象非静态成员变量的写操作会存在线程安全问题。

解决方式:在类中定一个ThreadLocal成员变量,将需要可变的成员变量保存在ThreadLocal中

@Component与@Bean区别

  1. 作用对象不同,@Component注解作用于类,@Bean作用于方法;
  2. @Component通过类路径扫描来自动装配到Spring容器中,@Bean通常是我们在标有该注解的方法中定义产生这个bean;
  3. @Bean注解自定义更强,当引用第三方库类需要装配Spring容器,只能使用@Bean

将一个类声明为Spring的bean注解有哪些?

一般使用@Autowired自动装配bean,要想把类标识成可用于 @Autowired 注解自动装配的 bean 的类,可以用以下方式

  • @Component :通用的注解,可标注任意类为 Spring 组件。如果一个Bean不知道属于哪个层,可以使用@Component 注解标注。
  • @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
  • @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao层。
  • @Controller : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。

Spring中的bean生命周期(重点)

对象实例化->属性注入->初始化->销毁

  1. 解析类得到BeanDefinition
  2. 有多个构造方法,推断构造方法
  3. 确定好构造方法,进行实例化得到对象
  4. 对对象中加了@Autowired注解的属性进行属性填充
  5. 回调Aware方法,比如BeanNameAware、BeanFactroyAware
  6. 调用BeanPostProcessor的初始化前的方法
  7. 调用初始化方法
  8. 调用BeanPostProcessor的初始化后的方法,这里会进行AOP
  9. 如果当前创建的bean是单例的则会把bean放入单例池
  10. 使用bean
  11. Spring容器关闭调用DisposableBean中的destroy()方法

Spring mvc

MVC是一种设计模式,Spring MVC是一个优秀的MVC框架

工作原理

  1. 用户发起一个请求达到前端控制器DispatcherServlet,接受用户请求与响应
  2. DispatcherServlet根据请求信息调用HandlerMapping,解析对应的请求Handler
  3. 解析到对应的Handler(相当于Controller)后,开始由HandlerAdapter适配器处理
  4. HandlerAdapter会根据Handler来调用真正的处理器处理请求,并处理相应的业务逻辑
  5. 处理器处理完后,返回一个ModelAndView对象,Model是返回的数据对象,View是一个逻辑的View
  6. 视图解析器会根据逻辑View查找给实际的View
  7. DispatcherServlet把返回的Mode传给View(视图宣传)
  8. 把View返回给请求者

Spring用到的设计模式

  • 工厂模式:Spring使用工厂模式通过BeanFactory、ApplicationContext创建bean的对象
  • 代理模式:AOP功能的实现
  • 单例模式:Spring中的Bean默认都是单例的
  • 模版模式:Spring中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式
  • 适配器模式:spring MVC 中也是用到了适配器模式适配Controller

Spring事务

Spring管理事务的方式

  1. 编程式事务,硬编码
  2. 声明式事务,配置文件

声明式事务

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

Spring事务的隔离级别

有5个表示隔离级别的常量

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

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

@Transaction

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

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




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 3223. Minimum Length of String After Operations
  • 1208. Get Equal Substrings Within Budget
  • 2730. Find the Longest Semi-Repetitive Substring
  • 1493. Longest Subarray of 1's After Deleting One Element
  • 2275. Largest Combination With Bitwise AND Greater Than Zero