Spring事务管理抽象
framework开发手册
Framework架构手册前言本框架基于Struts2.0+Spring2.5+Hibernate3.2架构所建,用于中小型企业网站或管理系统基础架构。
下面先简要介绍一下struts,spring,hibernate●Struts简介Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。
Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,所以说Struts是一个非常不错的应用框架。
●Spring简介Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。
Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。
Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器。
然而,这仅仅是完整图景中的一部分:Spring在使用IoC容器作为构建完关注所有架构层的完整解决方案方面是独一无二的。
Spring提供了唯一的数据访问抽象,包括简单和有效率的JDBC框架,极大的改进了效率并且减少了可能的错误。
Spring的数据访问架构还集成了Hibernate和其他O/R mapping解决方案。
Spring还提供了唯一的事务管理抽象,它能够在各种底层事务管理技术,例如JTA 或者JDBC事务提供一个一致的编程模型。
Spring提供了一个用标准Java语言编写的AOP 框架,它给POJOs提供了声明式的事务管理和其他企业事务--如果你需要--还能实现你自己的aspects。
这个框架足够强大,使得应用程序能够抛开EJB的复杂性,同时享受着和传统EJB相关的关键服务。
Spring还提供了可以和IoC容器集成的强大而灵活的MVC Web框架。
●Hibrenate简介Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Spring简介
Spring简介什么是Spring?spring是分层的avaSE以及javaEE应⽤于全栈的轻量级开源框架,以IOC(Inverse Of Control)控制反转,AOP(Aspect Oriented Programing)⾯向切⾯编程为核⼼,提供表现层SpringMVC以及持久层Spring,并且可整合多种其他开源框架。
spring的本质是管理对象,包括创建对象及维护对象之间的关系。
spring的优点1)⽅便解耦,简化开发通过spring的IOC可将对象的创建,以及对象之间的依赖都交由spring容器来进⾏管理,这样可以降低程序之间的耦合。
并且开发时也只需关注上层的应⽤,不⽤再多关注底层的应⽤。
2)AOP编程的⽀持spring⽀持AOP⾯向切⾯编程,许多OOP⾯向对象编程不能或很难实现的功能,都可通过AOP轻松实现。
3)声明式事务的⽀持可以将我们从单调烦闷的事务管理中解放出来,通过声明式事务的⽅式,可以灵活的进⾏事务管理,进⽽提⾼开发的质量和效率。
4)⽅便程序的测试可以⽤⾮容器依赖的编程⽅式进⾏⼏乎所有的测试⼯作,测试不再是昂贵的操作,⽽是随⼿可做的事情。
5)⽅便集成各种优秀的框架Spring可以降低各种框架的使⽤难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接⽀持。
6)降低javaEE的API的使⽤难度Spring对 JavaEE API(如 JDBC、JavaMail、远程调⽤等)进⾏了薄薄的封装层,使这些API 的使⽤难度⼤为降低。
7)spring框架的源码是经典学习的案例Spring的源代码设计精妙、结构清晰、匠⼼独⽤,处处体现着⼤师对Java设计模式灵活运⽤以及对 Java技术的⾼深造诣。
它的源代码⽆疑是Java技术的最佳实践的范例。
通过Spring进⾏解耦什么叫程序的耦合?在程序中,对象之间相互依赖,相互传递数据,这种相互关联的程度越⾼,程序的耦合度就越⾼。
Spring参考手册
第一部分 Spring框架的概述Spring框架是一个轻量级的解决方案和为构建企业级应用程序潜在的一站式服务。
然而,Spring是模块化的,允许你只使用那些你需要的部分,而忽略其他部分。
你可以在使用Struts时用Spring的IoC 容器,但你也可以只使用Hibernate 集成代码或JDBC抽象层。
Spring框架支持声明式事务管理、通过RMI或web服务远程访问你的逻辑,还有多种方式处理数据的持久化。
它还提供一个全能的MVC框架,并且能将AOP移植进你的软件。
Spring被设计为非侵入式的,意味着你的逻辑代码完全不必依赖于此框架。
虽然一些基于数据访问技术和Spring的库会存在于你的集成层(例如数据访问层),但是你的其他代码很容易隔离这些依赖。
1.开始使用Spring这篇手册提供了关于spring框架的详细信息,不仅有全面的特性,还有一些关于spring包含的潜在的概念(例如“依赖注入”)的背景知识。
如果你才刚刚开始,也许你应该从低级版的"Getting Started" 手册开始,从bbb://spring.io.访问。
为了更容易消化,这篇手册是专注于任务式。
2.Spring框架的介绍Spring框架是一个支持开发Java应用程序而提供全面的基础设施的Java平台,Spring处理基础部分从而你可以专注于你的应用。
spring 让你能够通过POJOs和向POJOs应用无侵入的企业服务就可以构建你的应用。
这些不仅能应用到Java SE而且还能应用到Java EE.一些作为一个开发者能够使用spring平台优势的例子●使Java方法可以执行数据库事务而不用去处理事务API●使本地Java方法可以执行远程过程而不用去处理远程API●使本地Java方法可以拥有管理操作而不用去处理JMXAPI●使本地Java方法可以执行消息处理而不用去处理JMSAPI2.1 依赖注入和控制反转Java应用程序——一个宽松的专业术语,小到一个Appletes大到运行在n层服务器上的企业级程序—通常由互相协作的对象而形成的适当的应用程序。
Spring事务配置的五种方式
Spring事务原理统观spring事务,围绕着两个核心PlatformTransactionManager和TransactionStatusspring提供了几个关于事务处理的类:TransactionDefinition //事务属性定义TranscationStatus //代表了当前的事务,可以提交,回滚。
PlatformTransactionManager这个是spring提供的用于管理事务的基础接口,其下有一个实现的抽象类AbstractPlatformTransactionManager,我们使用的事务管理类例如DataSourceTransactionManager等都是这个类的子类。
一般事务定义步骤:TransactionDefinition td = new TransactionDefinition();TransactionStatus ts = transactionManager.getTransaction(td);try{ //do sthmit(ts);}catch(Exception e){transactionManager.rollback(ts);}spring提供的事务管理可以分为两类:编程式的和声明式的。
编程式的,比较灵活,但是代码量大,存在重复的代码比较多;声明式的比编程式的更灵活。
编程式主要使用transactionTemplate。
省略了部分的提交,回滚,一系列的事务对象定义,需注入事务管理对象.void add(){transactionTemplate.execute( new TransactionCallback(){pulic Object doInTransaction(TransactionStatus ts){ //do sth}}}声明式:使用TransactionProxyFactoryBean:<bean id="userManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="transactionManager"><ref bean="transactionManager"/></property><property name="target"><ref local="userManagerTarget"/></property><property name="transactionAttributes"><props><prop key="insert*">PROPAGATION_REQUIRED</prop><prop key="update*">PROPAGATION_REQUIRED</prop><prop key="*">PROPAGATION_REQUIRED,readOnly</prop></props></property></bean>围绕Poxy的动态代理能够自动的提交和回滚事务org.springframework.transaction.interceptor.TransactionProxyFactoryBeanPROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。
spring事务原理
spring事务原理数据库系统内,事务指一系列连续的操作,这系列操作被看作一个整体,要么完全执行,要么完全不执行,不会出现执行部分的情况,这是数据库系统的基本特征之一。
在传统数据库系统中,事务的管理是由数据库系统自身提供的一种功能,然而随着数据库系统的复杂性的增加,数据库中的事务管理越来越复杂,对数据库操作有更多的要求,这样就催生了应用层事务管理技术,而当前最流行的事务管理技术是Spring事务。
Spring事务是一种基于AOP(面向切面编程)的分布式事务管理技术,它能够帮助系统更好的控制事务的处理过程,从而使系统内的数据更加有效率的共享,降低数据库事务的管理复杂度,提高数据库系统的可用性及性能。
Spring事务原理包括几个要素:事务模型、分布式事务处理框架、事务实现机制以及事务管理工具等。
一、事务模型Spring事务原理的核心是事务模型,即它把事务分为两种:提交成功事务和失败事务,在Spring提供的事务模型中,每个事务都只有两种结果,要么提交成功,要么提交失败,而不存在半提交的状态。
在Spring的事务模型中,事务的分类还要求事务的原子性,它要求一旦提交事务,事务就不会再次改变,或者改变的程度会很小。
原子性还表明事务的执行要么完全成功,要么完全失败,不会出现半成功半失败的情况。
二、分布式事务处理框架Spring提供了基于AOP技术的分布式事务处理框架,这种分布式事务处理框架能够有效地支持不同数据库之间的事务处理,它包括三个部分:事务管理器(TransactionManager)、事务拦截器(TransactionInterceptor)和事务事件监听器(TransactionListener)。
事务管理器是Spring对分布式事务的抽象,它可以处理不同类型的事务,它的实现通常会涉及到一些事务拦截器。
事务拦截器是Spring提供的一种安全机制,它能够在事务处理过程中,根据配置的规则,来拦截事务的执行,以便能够在事务处理过程中发现任何可能存在的问题,并对其进行调整,使得事务能够顺利的提交。
transactional注解的原理
Transactional注解的原理随着Spring框架的日益流行,越来越多的Java开发者开始使用Spring来构建他们的应用程序。
在Spring框架中,有一个非常重要的注解叫做Transactional,它用于声明一个方法或类需要进行事务管理。
本文将介绍Transactional注解的原理,包括它的工作原理、使用方法和一些注意事项。
一、Transactional注解的工作原理1.事务管理概述在数据库操作中,事务是一个非常重要的概念。
事务是一组数据库操作,要么全部执行成功,要么全部不执行。
如果其中任何一个操作失败,整个事务都应该回滚。
事务管理就是保证数据库操作的一致性和完整性的机制。
2.Transactional注解的作用在Spring框架中,开发者可以使用Transactional注解来声明一个方法或类需要进行事务管理。
当一个方法带有Transactional注解时,Spring框架会在方法执行前开启一个新的事务,在方法执行后根据执行结果决定事务是提交还是回滚。
3.内部工作原理Transactional注解的内部工作原理可以分为以下几个步骤:(1)Spring AOP代理:在运行时,Spring会为带有Transactional 注解的方法创建动态代理对象,使这些方法可以在运行前后执行一些额外的操作。
(2)事务管理器:Spring提供了多种事务管理器,比如DataSourceTransactionManager、HibernateTransactionManager等。
在运行时,Spring会根据配置选择合适的事务管理器来管理事务。
(3)事务切面:Spring利用AOP技术在Transactional注解所在的方法执行前开启事务,在方法执行后根据返回结果决定事务是提交还是回滚。
4.隔离级别和传播行为除了默认的事务管理行为外,Transactional注解还可以配置隔禅级别(Isolation)和传播行为(Propagation)。
spring原理和实现机制
spring原理和实现机制Spring框架是一个开源的应用程序框架,它提供了一种简单的方法来构建基于Java的企业级应用程序。
Spring框架的原理和实现机制主要包括:1. 控制反转(IoC):Spring使用控制反转(Inversion of Control,IoC)来管理应用程序中的对象。
传统的应用程序中,对象的创建和依赖关系管理是由程序员来实现的,而在Spring 中,对象的创建和管理工作由容器来完成。
容器会在应用程序启动时创建对象,并通过依赖注入的方式将对象之间的依赖关系注入到相应的对象中。
2. 依赖注入(DI):依赖注入是Spring框架的核心机制之一。
它指的是容器在创建对象时,自动将其所依赖的其他对象注入进来。
通过依赖注入,对象之间的解耦程度大大提高,使得应用程序更加灵活、可扩展和可维护。
3. 面向切面编程(AOP):Spring框架通过面向切面编程(Aspect-Oriented Programming,AOP)来实现横切关注点的模块化。
AOP可以将应用程序的核心逻辑(称为核心关注点)与横切关注点(如日志、事务管理等)分离开来,并通过切面来统一管理这些横切关注点。
4. 核心容器:Spring框架的核心是其容器(Container)。
容器使用BeanFactory接口作为底层容器的基础,并提供了ApplicationContext接口作为更高级的容器接口。
容器负责创建和管理应用程序中的对象,并提供了丰富的配置和管理功能。
5. 层次化的模块化架构:Spring的模块化架构使得开发者可以根据自己的需要选择使用不同的模块。
例如,Spring的核心模块包括IoC容器、AOP框架和BeanFactory等,而其他模块如Spring MVC、Spring Data等则提供了特定领域的解决方案。
6. 轻量级与非侵入性:Spring框架的设计理念是轻量级和非侵入性的。
它不依赖于特定的编程模型,可以与其他技术和框架无缝集成。
SpringBoot事务注解详解
SpringBoot事务注解详解SpringBoot事务注解详解@Transactionalspring 事务注解1.简单开启事务管理@EnableTransactionManagement // 启注解事务管理,等同于xml配置⽅式的 <tx:annotation-driven />2.事务注解详解默认遇到throw new RuntimeException(“…”);会回滚需要捕获的throw new Exception(“…”);不会回滚指定回滚@Transactional(rollbackFor=Exception.class)public void methodName() {// 不会回滚throw new Exception("...");}指定不回滚@Transactional(noRollbackFor=Exception.class)public ItimDaoImpl getItemDaoImpl() {// 会回滚throw new RuntimeException("注释");}如果有事务,那么加⼊事务,没有的话新建⼀个(不写的情况下)@Transactional(propagation=Propagation.REQUIRED)容器不为这个⽅法开启事务@Transactional(propagation=Propagation.NOT_SUPPORTED)readOnly=true只读,不能更新,删除@Transactional (propagation = Propagation.REQUIRED,readOnly=true)设置超时时间@Transactional (propagation = Propagation.REQUIRED,timeout=30)设置数据库隔离级别@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)3.指定事务管理器spring Boot 使⽤事务⾮常简单,⾸先使⽤注解 @EnableTransactionManagement 开启事务⽀持后,然后在访问数据库的Service⽅法上添加注解 @Transactional 便可。
propagation策略
Propagation策略是Spring框架中事务管理的一个关键属性,它决定了事务如何在不同的方法之间传播。
具体来说,Propagation策略定义了当一个事务方法被另一个事务方法调用时,应该如何使用事务。
以下是Spring中定义的几种Propagation策略:
1.PROPAGATION_REQUIRED:这是最常见的选择。
如果当前存在事务,那么就加入到这个事务中。
如果当前没有事务,就新建一个事务。
2.PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
3.PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
5.PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。
如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的
操作。
以上就是Spring中定义的所有Propagation策略。
这些策略可以帮助你更灵活地管理你的事务,以满足不同的业务需求。
Spring声明式事务注解之@EnableTransactionManagement解析
Spring声明式事务注解之@EnableTransactionManagement解析Spring声明式事务注解之@EnableTransactionManagement1. 说明@EnableTransactionManagement声明在主配置类上,表⽰开启声明式事务,其原理是通过@Import导⼊TransactionManagementConfigurationSelector组件,然后⼜通过TransactionManagementConfigurationSelector导⼊组件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;2. 原理分析@EnableTransactionManagement代码实现如下:@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented// 通过@Import导⼊TransactionManagementConfigurationSelector组件@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement {boolean proxyTargetClass() default false;AdviceMode mode() default AdviceMode.PROXY;int order() default Ordered.LOWEST_PRECEDENCE;}@EnableTransactionManagement通过@Import导⼊TransactionManagementConfigurationSelector;TransactionManagementConfigurationSelector的实现如下:public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {/*** {@inheritDoc}* @return {@link ProxyTransactionManagementConfiguration} or* {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and* {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively*/@Overrideprotected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:// 根据@EnableTransactionManagement的固定值PROXY,这⾥会导⼊AutoProxyRegistrar组件和ProxyTransactionManagementConfiguration组件 return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};default:return null;}}}所以TransactionManagementConfigurationSelector⼜导⼊了组件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;3. AutoProxyRegistrar分析3.1 AutoProxyRegistrar继承关系InfrastructureAdvisorAutoProxyCreator--AbstractAdvisorAutoProxyCreator--AbstractAdvisorAutoProxyCreator--ProxyProcessorSupport--SmartInstantiationAwareBeanPostProcessor // 跟AOP是原理是⼀样的--InstantiationAwareBeanPostProcessor--BeanPostProcessor--BeanFactoryAware3.2 AutoProxyRegistrar的所⽤AutoProxyRegistrar的作⽤跟AOP中的AnnotationAwareAspectJAutoProxyCreator是⼀样的,利⽤后置处理器机制在对象创建以后,包装对象,返回⼀个代理对象(增强器),代理对象执⾏⽅法利⽤拦截器链进⾏调⽤;InfrastructureAdvisorAutoProxyCreator继承SmartInstantiationAwareBeanPostProcessor,跟AOP的原理是⼀样的,也是通过@Transactional作为⽅法拦截的标记,把有事务管理的类作为⽬标类,⽣成代理对象,然后增强@Transactional标记的⽅法,在使⽤⽬标⽅法的时候,从IOC容器中获取的其实是被增强的代理类,且事务⽅法会被代理,跟AOP原理⼀样的;4. ProxyTransactionManagementConfiguration分析ProxyTransactionManagementConfiguration是⼀个配置类,想IOC容器中导⼊事务增强器(BeanFactoryTransactionAttributeSourceAdvisor),事务注解@Transactional的解析器(AnnotationTransactionAttributeSource)和事务⽅法拦截器(TransactionInterceptor);package org.springframework.transaction.annotation;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Role;import org.springframework.transaction.config.TransactionManagementConfigUtils;import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;import org.springframework.transaction.interceptor.TransactionAttributeSource;import org.springframework.transaction.interceptor.TransactionInterceptor;@Configurationpublic class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {/**事务增强器(Advisor),在事务类创建的时候,被AutoProxyRegistrar导⼊的组件InfrastructureAdvisorAutoProxyCreator拦截,InfrastructureAdvisorAutoProxyCreator拦截的逻就是增强事务类的事务⽅法,⽽BeanFactoryTransactionAttributeSourceAdvisor作为增强器,与需要增强的⽅法(这⾥是指被@Transactional标记的⽅法)进⾏匹配,匹配成功的增强器,最后转成拦截器(MethodInterceptor,就是下⾯的TransactionInterceptor),然后与⽬标⽅法⼀起在拦截器链中被执⾏,达到⽅法增强的效果;BeanFactoryTransactionAttributeSourceAdvisor的继承关系如下:BeanFactoryTransactionAttributeSourceAdvisor--AbstractBeanFactoryPointcutAdvisor--AbstractPointcutAdvisor--PointcutAdvisor--AdvisorAOP中AspectJPointcutAdvisor的继承关系如下,与AbstractPointcutAdvisor⼀样,都实现PointcutAdvisor--AspectJPointcutAdvisor--PointcutAdvisor--Advisor*/@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());advisor.setAdvice(transactionInterceptor());advisor.setOrder(this.enableTx.<Integer>getNumber("order"));return advisor;}/**@Transactional注解的解析类;负责解析事务⽅法上@Transactional中的各个参数配置,解析的时机是在创建事务类之后被增强的时候,匹配事务⽅法的时候⼀起被解析了AnnotationTransactionAttributeSource的继承关系如下:AnnotationTransactionAttributeSource--AbstractFallbackTransactionAttributeSource--TransactionAttributeSource通过⽅法org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>)解析出事务信息TransactionAttribute;AnnotationTransactionAttributeSource在⽅法findTransactionAttribute(Class<?>)中依赖于SpringTransactionAnnotationParser在解析事务类时,绑定事务⽅法与增强器的时候进⾏@Transactional注解解析;*/@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}/**被@Transactional标记的事务⽅法的拦截器,实际是⼀个MethodInterceptor保存了事务属性信息,事务管理器;在⽬标⽅法执⾏的时候;执⾏拦截器链;*/@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());if (this.txManager != null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}}在SpringTransactionAnnotationParser中parseTransactionAnnotation⽅法来解析@Transactional中的各个参数,其具体代码如下:protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");rbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");rbta.setIsolationLevel(isolation.value());rbta.setTimeout(attributes.getNumber("timeout").intValue());rbta.setReadOnly(attributes.getBoolean("readOnly"));rbta.setQualifier(attributes.getString("value"));ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();Class<?>[] rbf = attributes.getClassArray("rollbackFor");for (Class<?> rbRule : rbf) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}String[] rbfc = attributes.getStringArray("rollbackForClassName");for (String rbRule : rbfc) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");for (Class<?> rbRule : nrbf) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}String[] nrbfc = attributes.getStringArray("noRollbackForClassName");for (String rbRule : nrbfc) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}rbta.getRollbackRules().addAll(rollBackRules);return rbta;}spring 事务 @EnableTransactionManagement原理@EnableXXX原理:注解上有个XXXRegistrar,或通过XXXSelector引⼊XXXRegistrar,XXXRegistrar实现了ImportBeanDefinitionRegistrar的registerBeanDefinitions⽅法,给容器注册XXXCreator。
spring原理机制
spring原理机制转⾃:/nrain2/article/details/454593111,关于spring容器:spring容器是Spring的核⼼,该容器负责管理spring中的java组件,ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");//这种⽅式实例化容器,容器会⾃动预初始化所有Bean实例ctx.getBean("beanName");ApplicationContext 实例正是Spring容器。
ApplicationContext容器默认会实例化所有的singleton BeanSpring容器并不强制要求被管理组件是标准的javabean。
2,Spring的核⼼机制:依赖注⼊。
不管是依赖注⼊(Dependency Injection)还是控制反转(Inversion of Conctrol),其含义完全相同:当某个java实例(调⽤者)需要调⽤另⼀个java实例(被调⽤者)时,传统情况下,通过调⽤者来创建被调⽤者的实例,通常通过new来创建,⽽在依赖注⼊的模式下创建被调⽤者的⼯作不再由调⽤者来完成,因此称之为"控制反转";创建被调⽤者实例的⼯作通常由Spring来完成,然后注⼊调⽤者,所以也称之为"依赖注⼊"。
3,依赖注⼊⼀般有2中⽅式:设置注⼊:IoC容器使⽤属性的setter⽅式注⼊被依赖的实例。
<property name="" ref="">构造注⼊:IoC容器使⽤构造器来注⼊被依赖的实例。
<constructor-arg ref="">配置构造注⼊的时候<constructor-arg>可以配置index属性,⽤于指定该构造参数值作为第⼏个构造参数值。
spring事务详解(基于注解和声明的两种实现方式)
spring事务详解(基于注解和声明的两种实现⽅式)Spring事务( Transaction )事务的概念事务是⼀些sql语句的集合,作为⼀个整体执⾏,⼀起成功或者⼀起失败。
使⽤事务的时机⼀个操作需要多天sql语句⼀起完成才能成功程序中事务在哪⾥说明加在业务类的⽅法上⾯(public⽅法上⾯),表⽰业务⽅法执⾏时,需要事务的⽀持。
不同的事务管理器不同的数据库访问技术,处理事务是不同的1. 使⽤jdbc访问数据库,事务处理public void updateAccount(){Connection con = .....;con.setAutoCommit(false);state.insert();state.update();mit();con.setAutoCommit(true);}2. MyBatis执⾏数据库,处理事务public void updateAccount(){SqlSession sqlSession = SqlSessionFactory.openSession(false);try{sqlSession.insert(...);sqlSession.update(...);mit();}catch(Exception e){sqlSession.rollback();}}spring统⼀管理事务,把不同的数据库访问技术的事务处理统⼀起来使⽤spring的事务管理器,管理不同数据库访问技术的事务处理。
开发⼈员只需要掌握spring的事务处理⼀个⽅案,就可以实现使⽤不同数据库访问技术的事务管理。
尽管事务⾯向的是spring,有spring管理事务,做事务提交和回滚。
spring事务管理器spring框架使⽤事务管理器对象,管理所有的事务。
事务管理器接⼝: PlatFormTransactionManager作⽤:定义了事务的操作,主要是commit() , rollback()事务管理器有很多的实现类:⼀种数据库访问计数有⼀个实现类。
通过spring抽象路由数据源+MyBatis拦截器实现数据库自动读写分离
通过spring抽象路由数据源+MyBatis拦截器实现数据库⾃动读写分离前⾔之前使⽤的读写分离的⽅案是在mybatis中配置两个数据源,然后⽣成两个不同的SqlSessionTemplate然后⼿动去识别执⾏sql语句是操作主库还是从库。
如下图所⽰:好处是,你可以⼈为的去控制操作的数据库。
缺点也显⽽易见,就是代码⾮常⿇烦,总是需要去判断使⽤什么库,⽽且遇到事务的时候还必须特别⼩⼼。
这次我们利⽤spring抽象路由数据源+MyBatis拦截器来实现⾃动的读写分离,并且保证在使⽤事务的情况下也能正确。
结构如下图所⽰我们还是按照⽼套路,⾸先我会直接进⾏代码的实现,然后根据源码进⾏分析,最后做⼀个总结。
代码实现我们⼀共需要5个类和两个配置⽂件⾸先来说类/*** 全局动态数据源实体* @author LinkinStar**/public enum DynamicDataSourceGlobal {READ, WRITE;}这是⼀个枚举的实体,后⾯会⽤到/*** 动态数据源线程持有者* @author LinkinStar**/public final class DynamicDataSourceHolder {private static final ThreadLocal<DynamicDataSourceGlobal> holder = new ThreadLocal<DynamicDataSourceGlobal>();/*** 设置当前线程使⽤的数据源*/public static void putDataSource(DynamicDataSourceGlobal dataSource){holder.set(dataSource);}/*** 获取当前线程需要使⽤的数据源*/public static DynamicDataSourceGlobal getDataSource(){return holder.get();}/*** 清空使⽤的数据源*/public static void clearDataSource() {holder.remove();}}以上是两个⼯具,下⾯就是重点了⼀个是我们的主⾓,动态数据源,它继承⾃spring的抽象动态路由数据源/*** 动态数据源(继承⾃spring抽象动态路由数据源)* @author LinkinStar*/public class DynamicDataSource extends AbstractRoutingDataSource {private Object writeDataSource; //写数据源private Object readDataSource; //读数据源/*** 在初始化之前被调⽤,设置默认数据源,以及数据源资源(这⾥的写法是参考源码中的)*/@Overridepublic void afterPropertiesSet() {//如果写数据源不存在,则抛出⾮法异常if (this.writeDataSource == null) {throw new IllegalArgumentException("Property ‘writeDataSource‘ is required");}//设置默认⽬标数据源为主库setDefaultTargetDataSource(writeDataSource);//设置所有数据源资源,有从库添加,没有就添加Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put((), writeDataSource);if(readDataSource != null) {targetDataSources.put((), readDataSource);}setTargetDataSources(targetDataSources);super.afterPropertiesSet();}/*** 这是AbstractRoutingDataSource类中的⼀个抽象⽅法,⽽它的返回值是你所要⽤的数据源dataSource的key值 */@Overrideprotected Object determineCurrentLookupKey() {//根据当前线程所使⽤的数据源进⾏切换DynamicDataSourceGlobal dynamicDataSourceGlobal = DynamicDataSourceHolder.getDataSource();//如果没有被赋值,那么默认使⽤主库if(dynamicDataSourceGlobal == null|| dynamicDataSourceGlobal == DynamicDataSourceGlobal.WRITE) {return ();}//其他情况使⽤从库return ();}public void setWriteDataSource(Object writeDataSource) {this.writeDataSource = writeDataSource;}public Object getWriteDataSource() {return writeDataSource;}public Object getReadDataSource() {return readDataSource;}public void setReadDataSource(Object readDataSource) {this.readDataSource = readDataSource;}}然后是我们的另⼀个主⾓,动态数据源插件,实现MyBatis拦截器接⼝import java.util.Locale;import java.util.Map;import java.util.Properties;import java.util.concurrent.ConcurrentHashMap;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.executor.keygen.SelectKeyGenerator;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.SqlCommandType;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Plugin;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import org.springframework.transaction.support.TransactionSynchronizationManager;* 动态数据源插件,实现MyBatis拦截器接⼝* @author LinkinStar**/@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class }),@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class,ResultHandler.class }) })public class DynamicPlugin implements Interceptor {/*** 匹配SQL语句的正则表达式*/private static final String REGEX = ".*insert\\u0020.*|.*delete\\u0020.*|.*update\\u0020.*";/*** 这个map⽤于存放已经执⾏过的sql语句所对应的数据源*/private static final Map<String, DynamicDataSourceGlobal> cacheMap = new ConcurrentHashMap<>();@Overridepublic Object intercept(Invocation invocation) throws Throwable { boolean actualTransactionActive = TransactionSynchronizationManager.isActualTransactionActive(); if (!actualTransactionActive) {return invocation.proceed();}//从代理类参数中获取参数Object[] objects = invocation.getArgs();//其中参数的第⼀个值为执⾏的sql语句MappedStatement ms = (MappedStatement) objects[0];//当前sql语句所应该使⽤的数据源,通过sql语句的id从map中获取,如果获取到,则之前已经执⾏过直接取, DynamicDataSourceGlobal dynamicDataSourceGlobal = cacheMap.get(ms.getId());if (dynamicDataSourceGlobal != null) {DynamicDataSourceHolder.putDataSource(dynamicDataSourceGlobal);return invocation.proceed();}//如果没有,则重新进⾏存放//ms中获取⽅法,如果是查询⽅法if (ms.getSqlCommandType().equals(SqlCommandType.SELECT)) {//!selectKey 为⾃增id查询主键(SELECT LAST_INSERT_ID() )⽅法,使⽤主库if(ms.getId().contains(SelectKeyGenerator.SELECT_KEY_SUFFIX)) {dynamicDataSourceGlobal = DynamicDataSourceGlobal.WRITE;} else {BoundSql boundSql = ms.getSqlSource().getBoundSql(objects[1]);//通过正则表达式匹配,确定使⽤那⼀个数据源String sql = boundSql.getSql().toLowerCase(Locale.CHINA).replaceAll("[\\t\\n\\r]", " ");if(sql.matches(REGEX)) {dynamicDataSourceGlobal = DynamicDataSourceGlobal.WRITE;} else {dynamicDataSourceGlobal = DynamicDataSourceGlobal.READ;}}} else {dynamicDataSourceGlobal = DynamicDataSourceGlobal.WRITE;}//将sql对应使⽤的数据源放进map中存放cacheMap.put(ms.getId(), dynamicDataSourceGlobal);//最后设置使⽤的数据源DynamicDataSourceHolder.putDataSource(dynamicDataSourceGlobal);//执⾏代理之后的⽅法return invocation.proceed();}@Overridepublic Object plugin(Object target) {if (target instanceof Executor) {return Plugin.wrap(target, this);} else {return target;}}@Overridepublic void setProperties(Properties properties) {}}最后是我们的配⾓,动态数据源的事务管理器import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.TransactionDefinition;/*** 动态数据源事务管理器* @author LinkinStar**/public class DynamicDataSourceTransactionManager extends DataSourceTransactionManager {private static final long serialVersionUID = 1L;/*** 只读事务到读库,读写事务到写库*/@Overrideprotected void doBegin(Object transaction, TransactionDefinition definition) {//根据事务可读性进⾏判断boolean readOnly = definition.isReadOnly();//只读类型事务可以只⽤从库if(readOnly) {DynamicDataSourceHolder.putDataSource(DynamicDataSourceGlobal.READ);} else {DynamicDataSourceHolder.putDataSource(DynamicDataSourceGlobal.WRITE);}super.doBegin(transaction, definition);}/*** 清理本地线程的数据源(会被默认调⽤,调⽤时清除相应数据源)*/@Overrideprotected void doCleanupAfterCompletion(Object transaction) {super.doCleanupAfterCompletion(transaction);DynamicDataSourceHolder.clearDataSource();}}然后是两个配置⽂件,根据你⾃⼰的需要进⾏修改<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:tx="/schema/tx"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-4.3.xsd/schema/context/schema/context/spring-context.xsd/schema/tx/schema/tx/spring-tx.xsd"><context:property-placeholder location="classpath:resources/jdbc.properties"/><bean id="abstractDataSource" abstract="true" class="mons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /><property name="minIdle" value="${jdbc.minIdle}"></property><property name="maxIdle" value="${jdbc.maxIdle}"></property><property name="maxWait" value="${jdbc.maxWait}"></property><property name="maxActive" value="${jdbc.maxActive}"></property><property name="initialSize" value="${jdbc.initialSize}"></property><property name="testWhileIdle"><value>true</value></property><property name="testOnBorrow"><value>true</value></property><property name="testOnReturn"><value>false</value></property><property name="validationQuery"><value>SELECT 1 FROM DUAL</value></property><property name="validationQueryTimeout"><value>1</value></property><property name="timeBetweenEvictionRunsMillis"><value>3000</value></property><property name="numTestsPerEvictionRun"><value>2</value></property></bean><bean id="dataSourceRead" parent="abstractDataSource"><property name="url" value="${jdbc.url.read}" /><property name="username" value="${ername.read}"/><property name="password" value="${jdbc.password.read}"/></bean><bean id="dataSourceWrite" parent="abstractDataSource"><property name="url" value="${jdbc.url}" /><property name="username" value="${ername}"/><property name="password" value="${jdbc.password}"/></bean><bean id="dataSource" class="com.ssm.dao.data.DynamicDataSource"><property name="writeDataSource" ref="dataSourceWrite"></property><property name="readDataSource" ref="dataSourceRead"></property></bean><!--配置基于注解的声明式事务,默认使⽤注解来管理事务⾏为--><tx:annotation-driven transaction-manager="transactionManager"/><!--配置事务管理器(mybatis采⽤的是JDBC的事务管理器)--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!--注⼊数据库连接池--><property name="dataSource" ref="dataSource" /><!--扫描entity包,使⽤别名,多个⽤;隔开--><property name="typeAliasesPackage" value="com/ssm/entity" /><!--扫描sql配置⽂件:mapper需要的xml⽂件--><property name="mapperLocations" value="classpath*:com/ssm/dao/sqlxml/*.xml"></property><property name="plugins"><array><bean class="com.ssm.dao.data.DynamicPlugin" /></array></property></bean><bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" /></bean><!--配置扫描Dao接⼝包,动态实现DAO接⼝,注⼊到spring容器--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--注⼊SqlSessionFactory--><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><!-- 给出需要扫描的Dao接⼝--><property name="basePackage" value="com.ssm.dao"/></bean></beans>另外就是jdbc的配置⽂件,也需要根据⾃⼰进⾏修改,这边使⽤两个jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8ername=rootjdbc.password=123456jdbc.url.read=jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8ername.read=rootjdbc.password.read=123456jdbc.maxActive = 2jdbc.maxIdle =5jdbc.minIdle=1jdbc.initialSize =3jdbc.maxWait =3000⾄此所有的配置都已经完成,现在你已经可以进⾏测试,看看在查询和新增的时候是否使⽤的是不同的数据库。
platformtransactionmanager 用法
PlatformTransactionManager 是Spring 框架中的一个接口,用于管理事务,它提供了一种声明式方式来处理事务。
以下是使用PlatformTransactionManager 的基本步骤:1. 首先,需要在Spring 配置文件中定义一个TransactionManager bean。
例如:<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/></bean>2. 然后,在需要处理事务的方法上,使用Transactional 注解。
例如:Transactionalpublic void doSomething() {// 这里是需要处理事务的代码}3. 最后,在启动Spring 容器时,需要将事务管理器bean 注入到需要处理事务的类中。
例如:Autowiredprivate PlatformTransactionManager transactionManager;这样,当调用doSomething() 方法时,Spring 会自动将transactionManager 注入到该方法中,并使用transactionManager 来管理事务。
需要注意的是,PlatformTransactionManager 接口的实现类有多种,例如DataSourceTransactionManager、JdbcTransactionManager 等,具体使用哪种实现类需要根据具体的需求来选择。
同时,还需要注意事务的传播行为、隔离级别等配置。
spring 原理
spring 原理1、spring原理内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的。
Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象进行监督和控制(也就是在调用这类对象的具体方法的前后去调用你指定的模块)从而达到对一个模块扩充的功能。
这些都是通过配置类达到的。
Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring根据这些配置内部通过反射去动态的组装对象)Spring里用的最经典的一个设计模式就是:模板方法模式。
(这里我都不介绍了,是一个很常用的设计模式), Spring里的配置是很多的,很难都记住,但是Spring里的精华也无非就是以上的两点,把以上两点跟理解了也就基本上掌握了Spring.Spring AOP与IOC1、IoC:概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系核心:bean工厂;在Spring中,bean工厂创建的各个实例称作bean二、AOP(Aspect-Oriented Programming): 面向方面编程1、代理的两种方式:静态代理:针对每个具体类分别编写代理类;针对一个接口编写一个代理类;动态代理:针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类2、动态代理:不用写代理类,虚拟机根据真实对象实现的接口产生一个类,通过类实例化一个动态代理,在实例化动态代理时将真实对象及装备注入到动态代理中,向客户端公开的是动态代理,当客户端调用动态代理方法时,动态代理根据类的反射得到真实对象的Method,调用装备的invoke方法,将动态代理、Method、方法参数传与装备的invoke方法,invoke方法在唤起method方法前或后做一些处理。
spring框架技术期末试题及答案
spring框架技术期末试题及答案一、简答题1. 什么是Spring框架?它有哪些特点?Spring框架是一个开源的Java应用程序框架,它可以帮助开发者快速构建企业级应用程序。
Spring框架的特点包括灵活性、可扩展性、模块化和松耦合等。
2. Spring框架的主要模块有哪些?Spring框架主要包含以下模块:Spring Core、Spring Context、Spring AOP、Spring JDBC、Spring ORM、Spring Web MVC等。
3. 什么是Bean?它在Spring框架中的作用是什么?Bean是Spring框架中管理的对象,它们由Spring容器负责创建、组装和管理。
Bean的作用是实现应用程序中各个组件之间的解耦。
4. Spring框架支持哪些类型的依赖注入?Spring框架支持构造器注入、Setter方法注入和接口注入等多种类型的依赖注入。
5. 什么是AOP(面向切面编程)?Spring框架是如何实现AOP的?AOP是一种编程范式,用于将与业务逻辑无关的横切关注点(例如日志记录、事务管理等)从业务逻辑中分离出来。
Spring框架通过使用动态代理或字节码生成技术,在运行时将切面织入到目标对象中,从而实现AOP。
6. Spring框架中的事务管理是如何实现的?Spring框架通过使用TransactionManager和AOP来实现事务管理。
开发者可以使用@Transactional注解或XML配置来声明事务,并由Spring框架自动管理事务的提交和回滚。
7. Spring框架支持哪些类型的数据访问技术?Spring框架支持JDBC、ORM(如Hibernate、MyBatis)、JPA等多种类型的数据访问技术。
二、编程题1. 使用Spring框架实现一个简单的Web应用,包含以下功能:- 用户注册和登录- 用户信息修改- 用户列表展示2. 利用Spring框架实现一个简单的购物网站,包含以下功能:- 商品列表展示- 商品搜索- 购物车管理- 订单生成和支付三、综合题1. 请根据以下需求,在Spring框架中设计并实现一个图书管理系统:- 系统包括图书馆、图书、读者等实体- 图书馆可以添加、删除和管理图书- 读者可以注册、借阅和归还图书- 图书可以被多个读者同时借阅,但需要遵守借阅规则2. 设计并实现一个简单的员工管理系统,使用Spring框架进行开发。
Spring事务管理及与mybatis整合的事务管理
数据访问事务处理in Spring+Mybatis3.0事务---保证了用户的每一次操作都是可靠的,即使出现了异常的访问,也不至于破坏后台数据的完整性;Java事务简介事务必须符合ISO/IEC所定制的ACID原则1)A(atomicity):原子性在事务执行的过程中,任何的失败就将导致事务的任何修改失效,2)C(consistency):一致性事务回滚时,事务所执行的内容必须恢复到初始状态,即事务执行前的状态3)I(isolation):隔离性事务执行过程中对数据的修改,在提交之前的数据对其他事务不可见4)D(durability):持久性已经提交的数据在事务执行失败时,数据的状态都是正确的.事务分类:全局事务(分布式事务):由应用服务器来管理(如JTA),同时可以用于多个事务性的资源;本地事务本地事务和资源相关,主要通过JDBC来实现在实际应用中,存在一种容器管理事务,容器事务主要是由javaEE应用服务器提供,容器事务大多给予JTA完成,事实上这是在容器中覆盖了JDBC和JTA事务.事务特性分析(use spring)TransactionDefinition 接口来定义事务属性。
Code:public interface TransactionDefinition{int getIsolationLevel();int getPropagationBehavior();int getTimeout();boolean isReadOnly();}事务机制a)事务隔离级别隔离级别是指若干个并发的事务之间的隔离程度。
TransactionDefinition 接口中定义了五个表示隔离级别的常量:TransactionDefinition.ISOLATION_DEFAULT(默认值):表示使用底层数据库的默认隔离级别。
对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
Spring七种事务传播行为与五种事务隔离级别
Spring七种事务传播⾏为与五种事务隔离级别⼀、事务的传播⾏为:通过Propagation定义:<!-- 配置事务通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- 以⽅法为单位,指定⽅法应⽤什么事务属性:isolation:隔离级别 propagation:传播⾏为 read-only:是否只读--><tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/><!--上⾯的⽅式只适⽤单个⽅法,当我们业务有很多个⽅法都要操作事务时,则要配置很多个,可以使⽤下⾯的通配符配置⽅式--><tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>省略update.. detele.....</tx:attributes></tx:advice>readOnly:事务属性中的readOnly标志表⽰对应的事务应该被最优化为只读事务。
这是⼀个最优化提⽰。
在⼀些情况下,⼀些事务策略能够起到显著的最优化效果,例如在使⽤Object/Relational映射⼯具(如:或TopLink)时避免dirty checking(试图“刷新”)。
spring事务注解
spring事务注解@Transactional只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.Spring使用声明式事务处理,默认情况下,如果被注解的数据库操作方法中发生了unchecked异常,所有的数据库操作将rollback;如果发生的异常是checked 异常,默认情况下数据库操作还是会提交的。
这种默认的行为是可以改变的。
使用@Transactional注解的noRollbackFor和rollbackFor属性如:@Transactional(rollbackFor=Exception.class)可以使checked异常发生时,数据库操作也rollback、@Transactional(noRollbackFor=RuntimeException.class)可以使unchecked异常发生时也提交数据库操作。
也可以使用noRollbackForClassName、rollbackForClassName属性来指定一个异常类名的String数组来改变默认的行为。
读取数据库中的数据时是不需要事务管理的,这种情况下可以使用事务的传播行为来告诉Spring不需要开启事务,如:@Transactional(propagation = Propagation.NOT_SUPPORTED)。
事务的传播行为有:1. REQUIRED:表示业务方法需要在一个事务中处理,如果业务方法执行时已经在一个事务中,则加入该事务,否则重新开启一个事务。
这也是默认的事务传播行为;2. NOT_SUPPORTED:声明业务方法不需要事务,如果业务方法执行时已经在一个事务中,则事务被挂起,等方法执行完毕后,事务恢复进行;3. REQUIRES_NEW:表明业务方法需要在一个单独的事务中进行,如果业务方法进行时已经在一个事务中,则这个事务被挂起,并重新开启一个事务来执行这个业务方法,业务方法执行完毕后,原来的事务恢复进行;4. MANDATORY:该属性指定业务方法只能在一个已经存在的事务中进行,业务方法不能发起自己的事务;如果业务方法没有在一个既有的事务中进行,容器将抛出异常;5. SUPPORTS:该属性指定,如果业务方法在一个既有的事务中进行,则加入该事务;否则,业务方法将在一个没有事务的环境下进行;6. NEVER:指定业务方法不可以在事务中进行,如果业务方法执行时已经在一个事务中,容器将抛出异常;7. NESTED:该属性指定,如果业务方法在一个既有的事务中执行,则该业务方法将在一个嵌套的事务中进行;否则,按照REQUEIRED来对待。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring提供了一致的事务管理抽象。
这个抽象是Spring最重要的抽象之一,它有如下的优点:
∙为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、iBATIS 数据库层。
∙
∙提供比大多数事务API更简单的,易于使用的编程式事务管理API
∙
∙整合Spring数据访问抽象
∙
∙支持Spring声明式事务管理
JDBC事务容易使用,但也有明显的缺点:它们不能用于多个事务性资源,并且趋向侵入的编程模型。
Spring解决了这些问题。
它使应用开发者能够使用在任何环境下使用一致的编程模型。
你可以只写一次你的代码,这在不同环境下的不同事务管理策略中很有益处。
Spring同时提供声明式和编程式事务管理。
使用编程式事务管理,开发者直接使用Spring事务抽象,这个抽象可以使用在任何底层事务基础之上。
使用首选的声明式模型,开发者通常书写很少的事务相关代码,因此不依赖Spring或任何其他事务API。
Spring事务抽象的关键是事务策略的概念。
这个概念
由org.springframework.transaction.PlatformTransactionManager接口体现,如下:
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws
TransactionException; }
这首先是一个SPI接口,虽然它也可以在编码中使用。
注意按照Spring的哲学,这是一个接口。
因而如果需要它可以很容易地被模拟和桩化。
它也没有和一个查找策略如JNDI捆绑在一起:PlatformTransactionManager 的实现定义和其他Spring IoC容器中的对象一样。
这个好处使得即使使用JTA,也是一个很有价值的抽象:事务代码可以比直接使用JTA更加容易测试。
继续Spring哲学,TransactionException是unchecked的。
低层的事务失败几乎都是致命。
很少情况下应用程序代码可以从它们中恢复,不过应用开发者依然可以捕获并处理TransactionException。
getTransaction()根据一个类型为TransactionDefinition的参数返回一
个TransactionStatus对象。
返回的TransactionStatus对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事务)。
一个TransactionStatus也是和执行的线程关联的。
TransactionDefinition接口指定:
∙事务隔离:当前事务和其它事务的隔离的程度。
例如,这个事务能否看到其他事务未提交的写数据?
∙
∙事务传播:通常在一个事务中执行的所有代码都会在这个事务中运行。
但是,如果一个事务上下文已经存在,有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的事务中运行(大多数情况);或者挂起现有事务,创建一个新的事务。
∙
∙事务超时: 事务在超时前能运行多久(自动被底层的事务基础设施回滚)。
∙
∙只读状态: 只读事务不允许修改任何数据。
只读事务在某些情况下是一种非常有用的优化。
∙
这些设置反映了标准概念。
如果需要,请查阅讨论事务隔离层次和其他核心事务概念的资源:理解这些概念在使用Spring和其他事务管理解决方案时是非常关键的。
TransactionStatus接口为处理事务的代码提供一个简单的控制事务执行和查询事务状态的方法。
这个概念应该是熟悉的,因为它们在所有的事务API中是相同的:
public interface TransactionStatus {
boolean isNewTransaction();
void setRollbackOnly();
boolean isRollbackOnly();
}
但是使用Spring事务管理时,定义PlatformTransactionManager的实现是基本方式。
在好的Spring 风格中,这个重要定义使用IoC实现。