一、Spring事物
一、分类
编程式事物:代码中硬编码(不推荐使用)
声明式事物:配置文件中配置(推荐使用)
- 分类:
- 基于xml的声明式事物
- 基于注解的声明式事物
二、隔离级别
- ISOLATION_DEFAULT:使用后端数据库默认的隔离级别
- Mysql默认采用的REPEATABLE_READ隔离级别
- Oracle默认采用的READ_COMMITTED隔离级别
- ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- ISOLATION_READ_COMMITTED:允许读取并发事物已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
- ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事物自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别,串行化。
三、事物传播行为
一、支持当前事物的情况
- TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务:如果当前没有事务,则以非事务的方式继续运行。
- Transaction Definition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务:如果当前没有事务,则抛出异常。(mandatory:强制性)
二、不支持当前事物的情况
- TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事物,如果当前存在事物,则把当前事物挂起。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事物方式运行,如果当前存在事物,则抛出异常。
- TransactionDefinition.PROPAGATION_NEVER:以非事物方式运行,如果当前存在事物,则抛出异常。
三、其他情况
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事物的嵌套事务来运行;如果当前没有事物,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED
四、设计模式
- 工厂设计模式:Spring使用工厂模式通过BeanFactory、ApplicationContext创建Bean对象。
- 代理设计模式:Spring AOP功能的实现。
- 单例设计模式:Spring中的Bean默认都是单例的。
- 模版方法模式:Spring中jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的类,它们就使用到了模版模式。
- 包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
- 观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。
- 适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式、spring MVC中也是用到类适配器模式适配Controller。
五、Spring MVC
一、概述
Model1时代存在的问题:
- 将控制逻辑和表现逻辑混杂在一起,导致代码重用率极低。
- 前端和后端相互依赖,难以进行测试并且开发效率极低。
Model2时代存在的问题:
- 抽象和封装程度远远不够。
- 重复造轮子,降低了程序的可维护性和复用性。
MVC是一种设计模式,Spring MVC一款很优秀的MVC框架,天生与Spring框架集成。
Spring MVC下我们一般把后端项目分为Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)
二、工作原理
六、Spring bean
一、作用域
- singleton:唯一bean实例,Spring中的bean默认都是单例的。
- prototype:每次请求都会创建一个新的bean实例。
- request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
- session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。
- global-session:全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。
二、单例bean线程安全
多个线程操作同一个对象的时候,对这个对象的成员变量的写操作会存在线程安全问题。一般情况下,我们常用的Controller,Service,Dao这些Bean是无状态的。无状态的Bean不能保存数据,因此线程是安全的。
解决方法:
- 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中(推荐的一种方式)。
- 改变Bean的作用域为“prototype”:每次请求都会创建一个新的bean实例,自然不会存在线程安全问题。
三、@Component和@Bean的区别
- @Component:注解作用于类,通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径从中找出标识了需要装配的类自动装配到Spring的bean容器中)。
- @Bean:作用于方法,在标有该注解的方法中定义产生这个bean,@Bean告诉了Spring这是某个类的示例,当我们需要用它的时候还给我。
@Bean注解比@Component注解更强,而且很多地方我们只能通过@Bean注解来注册bean。比如当引用第三方库中的类需要装配到Spring容器时,则只能通过@Bean来实现。
四、类声明为Spring的bean的注解
- @Autowired注解自动装配bean
- @Component:通用的注解,可标注任意类为Spring组件。如果一个Bean不知道属于哪个层,可以使用@Component注解标注。
- @Repository:对应持久层即Dao层,主要用于数据库相关操作。
- @Service:对应服务层,主要涉及一些复杂的逻辑,需要用到Dao层。
- @Controller:对应Spring MVC控制层,主要用于接受用户请求并调用Service层返回数据给前端页面。