spring
2018-06-19 10:28:16 0 举报
AI智能生成
spring核心内容
作者其他创作
大纲/内容
spring
概念
Spring 是一个开源的轻量级 Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架,其目的是用于简化企业级应用程序开发
最根本的使命
简化开发
而他主要是通过:面向 Bean、依赖注入以及面向切面这三种方式来达成的
面向 Bean
Spring 提供了 IOC 容器通过配置文件或者注解的方式来管理对象之间的依赖关系
依赖注入
BeanFactory 支持两个对象模型
1,单例:模型提供了具有特定名称的对象的共享实例,可以在查询时对其进行检索。Singleton 是默认的也是最常用的对象模型。对于无状态服务对象很理想。
2,原型:模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时,原型模型最适合。
面向切面
面向切面编程,即 AOP,是一种编程思想,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面(切面),它将那些影响多个类的行为封装到可重用的模块中。
系统架构
核心容器
AOP 和设备支持
由 spring-aop、spring-aspects 和 spring-instrumentation 3 个模块组成
数据访问及集成
由 spring-jdbc、spring-tx、spring-orm、spring-jms 和 spring-oxm 5 个模块组成
Web
由 spring-web、spring-webmvc、spring-websocket 和 spring-webmvc-portlet 4 个模块组成。
报文发送
即 spring-messaging 模块
Test
即 spring-test 模块。
Spring IOC 体系结构
BeanFactory
Spring Bean 的创建是典型的工厂模式,这一系列的 Bean 工厂,也即 IOC 容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在 Spring 中有许多的 IOC 容器的实现供用户选择和使用,其相互关系如下
在 BeanFactory 里只对 IOC 容器的基本行为作了定义,根本不关心你的 bean 是如何定义怎样加载的。正如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心
BeanDefinition
SpringIOC 容器管理了我们定义的各种 Bean 对象及其相互的关系,Bean 对象在 Spring 实现中是以BeanDefinition 来描述的,其继承体系如下
Bean 的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean 的解析主要就是对 Spring 配置文件的解析。这个解析过程主要通过下图中的类完成
IOC 容器的初始化
IOC 容器的初始化包括 BeanDefinition 的 Resource 定位、载入和注册这三个基本的过程
ApplicationContext 系列容器也许是我们最熟悉的,因为 web 项目中使用的 XmlWebApplicationContext 就属于这个继承体系,还有 ClasspathXmlApplicationContext 等,其继承体系如下图所示
IOC 容器初始化的基本步骤
1.初始化的入口在容器实现中的 refresh()调用来完成
2.对 bean 定义载入 IOC 容器使用的方法是 loadBeanDefinition
3.然后我们就可以通过 BeanFactory 和 ApplicationContext 来享受到 SpringIOC 的服务了
IOC 容器的依赖注入
依赖注入发生的时间
当 Spring IOC 容器完成了 Bean 定义资源的定位、载入和解析注册以后,IOC 容器中已经管理类 Bean定义的相关数据,但是此时 IOC 容器还没有对所管理的 Bean 进行依赖注入
(1).用户第一次通过 getBean 方法向 IOC 容索要 Bean 时,IOC 容器触发依赖注入
(2).当用户在 Bean 定义资源中为<Bean>元素配置了 lazy-init 属性,即让容器在解析注册 Bean 定义时进行预实例化,触发依赖注入
高级特性
lazy-init 属性对 Bean 预初始化
FactoryBean 产生或者修饰 Bean 对象的生成
BeanPostProcessor 后置处理器的实现
BeanPostProcessor 后置处理器是 Spring IOC 容器经常使用到的一个特性,这个 Bean 后置处理器是一个监听器,可以监听容器触发的 Bean 声明周期事件。后置处理器向容器注册以后,容器中管理的 Bean就具备了接收 IOC 容器事件回调的能力
autowiring 自动装配功能
beanFactoryPostprocess beanPostprocess
Spring AOP 设计原理及具体实践
AOP 的相关概念
目标对象(Target Object) ) :被一个或者多个切面所通知的对象。例如,AServcieImpl 和 BServiceImpl,当然在实际运行时,Spring AOP 采用代理实现,实际 AOP 操作的是 TargetObject 的代理对象。
AOP 理 代理( (AOP Proxy ):在 Spring AOP 中有两种代理方式,JDK 动态代理和 CGLIB 代理。默认情况下,TargetObject实现了接口时,则采用 JDK 动态代理,例如,AServiceImpl;反之,采用 CGLIB 代理,例如,BServiceImpl。强制使用 CGLIB 代理需要将 <aop:config>的 proxy-target-class 属性设为 true
切面(Aspect ):官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”。“切面”在ApplicationContext 中<aop:aspect>来配置
连接点( (Joinpoint ):程序执行过程中的某一行为,例如,MemberService .get 的调用或者 MemberService .delete抛出异常等行为。
通知(Advice) ) :“切面”对于某个“连接点”所产生的动作。其中,一个“切面”可以包含多个“Advice”。
前置通知(Before advice ):在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。ApplicationContext 中在<aop:aspect>里面使用<aop:before>元素进行声明。例如,TestAspect 中的 doBefore 方法。
后置通知( (After advice) ): :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext中在<aop:aspect>里面使用<aop:after>元素进行声明。例如,ServiceAspect 中的 returnAfter 方法,所以 Teser 中调用UserService.delete 抛出异常时,returnAfter 方法仍然执行
返回后通知( (After return advice) ): :在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext中在<aop:aspect>里面使用<after-returning>元素进行声明。
环绕通知( (Around advice) ): :包围一个连接点的通知,类似 Web 中 Servlet 规范中的 Filter 的 doFilter 方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。ApplicationContext 中在<aop:aspect>里面使用<aop:around>元素进行声明。例如,ServiceAspect 中的 around 方法。
抛出异常后通知( (After throwing advice) ): :在方法抛出异常退出时执行的通知。ApplicationContext 中在<aop:aspect>里面使用<aop:after-throwing>元素进行声明。例如,ServiceAspect 中的 returnThrow 方法。
切入点( (Pointcut ) :匹配连接点的断言,在 AOP 中通知和一个切入点表达式关联。切面中的所有通知所关注的连接点,都由切入点表达式来决定
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?
modifiers-pattern:方法的操作权限 ret-type-pattern:返回值 declaring-type-pattern:方法所在的包 name-pattern:方法名 parm-pattern:参数名 throws-pattern:异常
其中,除 ret-type-pattern 和 name-pattern 之外,其他都是可选的。上例中,execution(* com.spring.service.*.*(..))表示com.spring.service 包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。
Transaction
什么是事务
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)
特点
事务是恢复和并发控制的基本单位
4 个属性
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
事务的基本原理
Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring 是无法提供事务功能的
Spring 事务的传播属性
所谓 spring 事务的传播属性,就是定义在存在多个事务同时存在的时候,spring 应该如何处理这些事务的行为。这些属性在 TransactionDefinition 中定义,具体常量的解释见下表
假设外层事务 Service A 的 Method A() 调用 内层 Service B 的 Method B()
PROPAGATION_REQUIRED
支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。
如果 ServiceB.methodB() 的事务级别定义为 PROPAGATION_REQUIRED,那么执行 ServiceA.methodA()的时候 spring 已经起了事务,这时调用 ServiceB.methodB(),ServiceB.methodB() 看到自己已经运行在 ServiceA.methodA() 的事务内部,就不再起新的事务。假如 ServiceB.methodB() 运行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在 ServiceA.methodA() 或者在 ServiceB.methodB() 内的任何地方出现异常,事务都会被回滚。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
比如我们设计 ServiceA.methodA() 的事务级别为 PROPAGATION_REQUIRED,ServiceB.methodB() 的事务级别为 PROPAGATION_REQUIRES_NEW。那么当执行到 ServiceB.methodB() 的时候,ServiceA.methodA() 所在的事务就会挂起,ServiceB.methodB() 会起一个新的事务,等待 ServiceB.methodB() 的事务完成以后,它才继续执行。他与 PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为 ServiceB.methodB() 是新起一个事务,那么就是存在两个不同的事务。如果 ServiceB.methodB() 已经提交,那么 ServiceA.methodA()失败回滚,ServiceB.methodB() 是不会回滚的。如果 ServiceB.methodB() 失败回滚,如果他抛出的异常被 ServiceA.methodA() 捕获,ServiceA.methodA() 事务仍然可能提交(主要看 B 抛出的异常是不是 A 会回滚的异常)。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
假设 ServiceB.methodB() 的事务级别为 PROPAGATION_SUPPORTS,那么当执行到 ServiceB.methodB()时,如果发现 ServiceA.methodA()已经开启了一个事务,则加入当前的事务,如果发现ServiceA.methodA()没有开启事务,则自己也不开启事务。这种时候,内部方法的事务性完全依赖于最外层的事务。
PROPAGATION_MANDATORY
支持当前事务,如果当前没有事务,就抛出异常
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按 REQUIRED 属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager 事务管理器起效
a.捕获异常,执行异常分支逻辑
数据库隔离级别
隔离级别
隔离级别的值
导致的问题
Read-Uncommitted
0
导致脏读
Read-Committed
1
避免脏读,允许不可重复读和幻读(默认的)
Repeatable-Read
2
避免脏读,不可重复读,允许幻读
Serializable
3
串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重
脏读
一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。
不可重复读
一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。
幻读
第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改
总结
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB
Spring中的隔离级别
ISOLATION_DEFAULT
这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与 JDBC 的隔离级别相对应。
ISOLATION_READ_UNCOMMITTED
这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读
ISOLATION_READ_COMMITTED
保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
ISOLATION_REPEATABLE_READ
这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读
ISOLATION_SERIALIZABLE
这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行
Spring MVC 框架设计原理
Spring MVC 请求处理流程
④ ⑤ ⑥:视图解析器解析 ModelAndView 对象并返回对应的视图给客户端
Spring MVC 的工作机制
这样就可以根据 request 快速定位到 controller
Spring MVC 源码分析
Spring MVC 的优化
0 条评论
回复 删除
下一页