1、Spring Bean的作用域之间有什么区别?
在spring中,可以在<bean>的scope属性设置bean的作用域,以决定这个bean是单实例的还是多实例的;
默认情况下,spring只为每个ioc容器声明的bean创建唯一一个实例,整个ioc容器范围内都能共享这个实例,所有后续的getBean()和bean的引用都将返回这个唯一的bean实例,该作用域被称为singleton,他说所有bean的默认作用域;
singleton:在ioc容器中存在一个bean实例,bean以单实例的方式存在;当ioc容器被创建时,实例化该bean;
prototype:当ioc容器被创建时,不会实例化该bean;每次调用getBean()时都会返回一个新的bean实例;
request:每次http请求都会返回一个新的bean实例,该作用域只适用于WebApplicationContext环境;
session:同一个http session共享一个bean实例,该作用域只适用于WebApplicationContext环境;
2、Spring事务的传播行为
事务传播属性可以在注解@Transactional的propagation属性中定义;
当事务方法被另一个事务方法调用时,必须指定事务该如何传播;
例如:方法可能继续在现有的事务中运行,也有可能开启一个新的事务,并在自己的事务中运行;
事务的传播由传播属性来定义,spring定义了7种类型的传播行为;
REQUIRED:如果有事务在运行,当前方法就在这个事务内运行,否则就启动一个新事务,并在自己的事务内运行;
REQUIRES_NEW:当前方法必须启动一个新事务,并在自己的事务内运行,如果有事务正在运行,应该将它挂起;
SUPPORTS:如果有事务在运行,当前方法就在这个事务内运行,否则它可以不运行在事务中;
NOT_SUPPORTED:当前方法不应该运行在事务中,如果有事务正在运行,应该将它挂起;
MANDATORY:当前方法必须运行在事务中,如果没有事务正在运行,就抛出异常;
NEVER:当前方法不应该运行在事务中,如果有事务正在运行,就抛出异常;
NESTED:如果有事务在运行,当前方法就在这个事务的嵌套事务内运行,否则就启动一个新事务,并在自己的事务内运行;
事务并发性的问题:
假设有两个事务t1和t2并发执行;
1、脏读
t1将某条记录的age值从20修改到30;
t2读取到t1更新后的值30;
t1回滚,age值恢复为20;
t2读取到的值是一个无效的值;
2、不可重复读
t1读取age的值20
t2将age修改为30
t1再次读取age值为30,和第一次值不一致
3、幻读
t1读取表中一部分数据
t2向表中插入一条新数据
t1再次读取时,多出了一条新数据
解决事务并发问题的方法
隔离级别:
事务的隔离级别可以在注解@Transactional的isolation属性中定义;
数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。
一个事务与其它事务隔离的程度称为隔离级别。
SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据数据一致性就越好,但并发性就越弱。
1、读未提交:READ UNCOMMITTED
允许t1读取t2未提交的数据;
2、读已提交:READ COMMITTED(Oracle默认隔离级别,开发时通常使用的隔离级别)
要求t1只能读取t2已提交的数据;
3、可重复读:REPEATABLE READ(MySql默认隔离级别)
确保t1可以多次从一个字段中读取相同的值,即t1执行期间,禁止其它事务对这个值进行更新;
4、串行化:SERIALIZABLE
确保t1可以多次从一个表中读取到相同的行,在t1执行期间,禁止其它事务对这个表进行新增、删除、修改操作,可以避免任何并发问题,但性能较差;
各个隔离级别解决并发问题能力:
脏读 | 不可重复读 | 幻读 | |
READ UNCOMMITTED | 有 | 有 | 有 |
READ COMMITTED | 无 | 有 | 有 |
REPEATABLE READ | 无 | 无 | 有 |
SERIALIZABLE | 无 | 无 | 无 |
各个数据库产品对事务隔离级别的支持程度:
oracle | mysql | |
READ UNCOMMITTED | no | yes |
READ COMMITTED | yes(默认) | yes |
REPEATABLE READ | no | yes(默认) |
SERIALIZABLE | yes | yes |
示例代码:
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED)
3、Spring MVC执行流程
-
一个请求匹配前端控制器 DispatcherServlet 的请求映射路径(在 web.xml中指定), WEB 容器将该请求转交给 DispatcherServlet 处理
-
DispatcherServlet 接收到请求后, 将根据 请求信息 交给 处理器映射器 (HandlerMapping)
-
HandlerMapping 根据用户的url请求 查找匹配该url的 Handler,并返回一个执行链
-
DispatcherServlet 再请求 处理器适配器(HandlerAdapter) 调用相应的 Handler 进行处理并返回 ModelAndView 给 DispatcherServlet
-
DispatcherServlet 将 ModelAndView 请求 ViewReslover(视图解析器)解析,返回具体 View
-
DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)
-
DispatcherServlet 将页面响应给用户
组件说明:
-
DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,
由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
-
HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,
例如:配置文件方式,实现接口方式,注解方式等。
-
Handler:处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
-
HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
-
ViewResolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,
再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
-
View:视图
springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。