Spring 自动事务代理
记一次实际开发过程中遇到事务报错问题Transactionsynchronizationi。。。
记⼀次实际开发过程中遇到事务报错问题Transactionsynchronizationi。
⼀:问题场景 在⼀次http请求的后台接⼝中返回结果中出现了这个错误信息“Transaction synchronization is not active”,意思是“事务同步器没有激活”,但是被调⽤的接⼝已经添加了@Transactional注解,所以百思不得不得其解为什么还会报这个错误,那么是什么原因引起了这个异常呢?⾃⼰通过百度⼤神博客终于找到⼀篇相似的⽂章解决了⾃⼰的问题,今天就是把解决⽅案记录下来为以后再出现类似情况提供解决⽅案。
⼆:出现原因 Google搜索⼀番之后,发现了这篇⽂章Spring的TransactionEventListener,⽂中提到了可能出现这个错误信息的⼀种情况: @EventListener public void afterRegisterSendMail(MessageEvent event) { // Spring 4.2 之前 TransactionSynchronizationManager.registerSynchronization( new TransactionSynchronizationAdapter() { @Override public void afterCommit() { internalSendMailNotification(event); } }); } 上⾯的代码将在事务提交后执⾏.如果在⾮事务context中(就是⽅法未开启spring事务)将抛出ng.IllegalStateException: Transaction synchronization is not active 于是找到⾃⼰代码中的TransactionSynchronizationManager部分,果然在当前http请求链路中的⼀个接⼝⾥发现了类似的代码: TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { try { byte[] bytes = JSON.toJSONBytes(task, new SerializeConfig()); MessageProperties messageProperties = new MessageProperties(); messageProperties.setMessageId(idWorker.nextStringId()); Message message = new Message(bytes, messageProperties); salaryFileMsgProducer.sendSalaryFileMsg(message); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } } }); 想必是执⾏这段代码的时候报的异常,但是上⾯那篇⽂章说了引起这个异常的原因是“在⾮事务context中注册同步器”,难道当前事务没有开启?我们的业务代码⼀般都是使⽤spring的注解@Transactional来开启事务,那么去看⼀下开启事务的代码⽚段。
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事务的实现原理主要依赖于数据库或者其他存储系统的事务功能。
1. 数据库事务支持:Spring事务的实现依赖于数据库的事务功能。
通常情况下,数据库支持ACID(原子性、一致性、隔离性和持久性)事务特性,可以通过SQL的BEGIN、COMMIT 和ROLLBACK等命令来控制事务的开始、提交和回滚操作。
2. 事务管理器:Spring框架提供了事务管理器(TransactionManager)接口,用于管理事务的开始、提交和回滚等操作。
事务管理器可以根据配置信息选择不同的实现,如使用JDBC事务管理器(DataSourceTransactionManager)或者JTA事务管理器(JtaTransactionManager)等。
3. 编程式事务:Spring框架提供了编程式事务管理的支持,通过编写代码显式地控制事务的边界。
开发者可以在代码中使用事务管理器的API来手动管理事务,包括事务的开始、提交和回滚等操作。
这种方式灵活性较高,但也需要开发者手动处理事务的细节。
4. 声明式事务:Spring框架还提供了声明式事务管理的支持,通过使用注解或者XML配置来定义事务的属性和边界。
开发者可以使用@Transactional注解或者事务配置元素来标记方法或者类,指示该方法或者类在执行时需要开启事务。
Spring会在方法调用前后自动地管理事务的开始、提交和回滚等操作。
5. 事务传播行为:Spring事务还支持事务传播行为的定义,即一个方法调用另一个带有事务的方法时事务该如何传播。
例如,当前方法可能会暂停事务、加入到现有的事务中或者创建一个新的事务。
Spring提供了多种事务传播行为的选项,如REQUIRED、REQUIRES_NEW、NESTED等,可以根据需要进行配置。
总的来说,Spring事务的实现原理是通过与数据库或其他存储系统的事务功能结合,通过事务管理器来管理事务的开始、提交和回滚等操作。
SpringAOP的原理和应用场景
SpringAOP的原理和应用场景SpringAOP(Aspect-Oriented Programming)是Spring框架中的一个重要组成部分,它提供了一种通过预定义的方式,将横切关注点(Cross-cutting Concerns)与业务逻辑进行解耦的机制。
本文将介绍SpringAOP的原理及其在实际应用场景中的应用。
一、SpringAOP的原理SpringAOP基于代理模式(Proxy Pattern)实现。
在SpringAOP中,通过生成与原始类(被代理类)具有相同接口的代理类,将横切逻辑编织到业务逻辑中。
在运行时,当调用代理类的方法时,会在方法执行前、后或异常抛出时插入相应的横切逻辑代码。
具体而言,SpringAOP使用了以下几个核心概念:1. 切面(Aspect):切面是横切逻辑的模块化单元,它包含了一组通知(Advice)和切点(Pointcut)。
2. 通知(Advice):通知定义了实际的横切逻辑代码,并规定了何时执行该代码。
SpringAOP提供了五种类型的通知:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。
3. 切点(Pointcut):切点指定了在哪些连接点(Join Point)上执行通知。
连接点可以是方法调用、属性访问等程序执行的点。
4. 连接点(Join Point):连接点是程序执行过程中的一个特定点,如方法调用前、方法调用后等。
通知通过切点来选择连接点。
5. 织入(Weaving):织入是将切面应用到目标对象,并创建代理对象的过程。
织入可以在编译时、类加载时或运行时进行。
二、SpringAOP的应用场景SpringAOP可应用于各种场景,用于解决跨越多个模块或类的横切关注点问题。
以下是一些常见的SpringAOP应用场景:1. 日志记录:通过在关键方法的前后插入日志代码,实现对系统运行状态的监控和记录。
Spring MVC 事物
public class StarDAO extends HibernateDaoSupport implements IStarDao{........}
如何创建事务
使用事务解决银行转账问题
开始事务(指定事务从此处开始,后 ……关键语句讲解……… 续的T-SQL语句都是一个整体) BEGIN TRANSACTION /*--定义变量,用于累计事务执行过程中的错误--*/ DECLARE @errorSum INT SET @errorSum=0 --初始化为0,即无错误 /*--转账:张三的账户少1000元,李四的账户多1000元*/ UPDATE bank SET currentMoney=currentMoney-1000 WHERE customerName='张三' SET @errorSum=@errorSum+@@error 累计是否有错误 UPDATE bank SET currentMoney=currentMoney+1000 WHERE customerName='李四' SET @errorSum=@errorSum+@@error --累计是否有错误
@@ERROR只能判断当前一条T-SQL语句执行是否有错, 为了判断事务中所有T-SQL语句是否有错,我们需要对 错误进行累计;
如何创建事务
了解事务的分类: 显示事务:用BEGIN TRANSACTION明确指定事务的 开始,这是最常用的事务类型 隐性事务:通过设置SET IMPLICIT_TRANSACTIONS ON 语句,将隐性事务模式设置为打开,下一个语 句自动启动一个新事务。当该事务完成时,再下 一个 T-SQL 语句又将启动一个新事务 自动提交事务:这是 SQL Server 的默认模式, 它将每条单独的 T-SQL 语句视为一个事务,如果 成功执行,则自动提交;如果错误,则自动回滚
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 便可。
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。
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声明式事务@Transactional详解,事务隔离级别和传播行为
Spring声明式事务@Transactional详解,事务隔离级别和传播⾏为@Transactional注解⽀持9个属性的设置,这⾥只讲解其中使⽤较多的三个属性:readOnly、propagation、isolation。
其中propagation属性⽤来枚举事务的传播⾏为,isolation⽤来设置事务隔离级别,readOnly进⾏读写事务控制。
@Service@Transactional(readOnly = true)public class AppTradeRec2Service extends BaseService {@Autowiredprivate AppTradeRecDao appTradeRecDao;@Autowiredprivate ConsInfoDao consInfoDao;@Transactional(readOnly = false)public void payCharge(TradeRec tradeRec) {User usr = UserUtils.getUser();ConsInfo cons = consInfoDao.getByUser(usr.getId());//修改交易记录tradeRec.setPayBefore(cons.getAccountAmt());tradeRec.setPayAfter(cons.getAccountAmt() - tradeRec.getRcvAmt());tradeRec.setIsPay("99");appTradeRecDao.save(tradeRec);//修改账户余额cons.setAccountAmt(cons.getAccountAmt() - tradeRec.getRcvAmt());consInfoDao.save(cons);}}⼀、readOnly读写事务控制readOnly=true表明所注解的⽅法或类只是读取数据。
Spring事务之七(事务自动提交)
Spring事务之七(事务自动提交)一、MySQL数据库事务自动提交对于mysql数据库,默认情况下,数据库处于自动提交模式。
每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。
对于正常的事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式,下面是查看方式:查看是否自动提交命令(ON表示开启自动提交,值为1,OFF表示关闭自动提交,值为0):关闭自动提交后,则用户将一直处于某个事务中,直到执行一条commit提交或rollback语句才会结束当前事务重新开始一个新的事务。
二、Spring连接如果结合Spring来获取数据库连接,就不用担心,spring会将底层连接的自动提交特性设置为false,先看下Spring事务配置:1.<!-- 配置事务 -->2.<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransac tionManager">3.<property name="dataSource" ref="dataSource" />4.</bean>5.<tx:annotation-driven transaction-manager="transactionManager"/>上面配置中,重要的是类:org.springframework.jdbc.datasource.DataSourceTransactionMa nager,看其对自动提交的处理:1.protected void doBegin(Object transaction, TransactionDefinition definition) {2.3.//......4.5.if(con.getAutoCommit()) {6.txObject.setMustRestoreAutoCommit(true);7.if(this.logger.isDebugEnabled()) {8.this.logger.debug("Switching JDBC Connection [" + con + "] to manual commit");9.}10.con.setAutoCommit(false);11.}12.13.//......14.15.}三、建议:当一个连接关闭时,如果有未提交的事务则回滚任何未提交的事务(C3P0默认的策略,C3P0的autoCommitOnClose属性默认是false)。
service 内部调用事务失效原理
service 内部调用事务失效原理
service内部调用事务失效的原理是Spring数据库事务的约定和其实现原理AOP(面向切面编程)。
当service类的一个方法调用另一个方法时,这个调用过程是在类自身内部完成的,而不是通过Spring代理的Bean进行的。
这就意味着,被调用的方法上的事务声明在这个内部调用过程中不会起作用。
Spring的事务管理是通过AOP实现的,而AOP的原理是动态代理。
在自调用的过程中,是类自身的调用,而不是代理对象去调用,那么就不会产生AOP,这样Spring就不能把你的代码织入到约定的流程中,于是就产生了现在看到的失败场景。
因此,当你在某个方法上声明它需要事务的时候,如果这个类还有其他开发者,你将不能保证这个方法真的会在事务环境中。
换句话说,Spring的事务传播策略在内部方法调用时将不起作用。
不管你希望某个方法需要单独事务,是RequiresNew,还是要嵌套事务,要Nested,等等,统统不起作用。
Spring笔记(5)-声明式事务@EnableTransactionManagement。。。
Spring笔记(5)-声明式事务@EnableTransactionManagement。
⼀.背景 前⾯详解了,对于配置都使⽤到了xml配置,今天介绍Spring事务的注解开发,例如下⾯例⼦:1. 配置类:注册数据源、JDBC模板、事务管理器//包扫描,将包下的dao、service注册到Spring容器中@ComponentScan("com.hrh")//开启基于注解的事务管理,跟@Transactional注解配套使⽤@EnableTransactionManagement//表明TxConfig是配置类@Configurationpublic class TxConfig {//注册数据源@Beanpublic DataSource dataSource() throws Exception {ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();comboPooledDataSource.setUser("xxx");comboPooledDataSource.setPassword("xxx");comboPooledDataSource.setJdbcUrl("jdbc:mysql://xxx:3306/xxx");comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");return comboPooledDataSource;}//注册jdbc模板@Beanpublic JdbcTemplate jdbcTemplate() throws Exception {return new JdbcTemplate(dataSource());}//注册事务管理器来控制事务@Beanpublic PlatformTransactionManager manager() throws Exception {return new DataSourceTransactionManager(dataSource());}}2. 业务代码:@Repositorypublic class UserDao {@Autowiredprivate JdbcTemplate jdbcTemplate;public void insert(){String sql ="insert into tab_person(name,age) values(?,?)";String name = UUID.randomUUID().toString().substring(0, 5);jdbcTemplate.update(sql,name,19);}}@Servicepublic class UserService{@Autowiredprivate UserDao userDao;//添加事务@Transactionalpublic void insert() {userDao.insert();System.out.println("插⼊完成。
用AspectJ方式来处理Spring的@Transactional注解式事务
⽤AspectJ⽅式来处理Spring的@Transactional注解式事务为节省你的时间,如果你你不清楚什么是Spring 、AspectJ、事务处理,本⽂就不适合你看。
你可以路过就⾛。
在⽹络应⽤中,我们⼏乎总是需要严密控制我们spring应⽤中的数据库事务的启动和结束。
为做到这⼀点,我们或多或少都已经通过AOP来做这些事情。
但⼀般都是在XXService、或XXController中封装处理请求的⽅法。
Spring有内置注解⽀持,因⽽你可以简单地通过@Transactional注解你的⽅法或类,并在配置⽂件中添加<tx:annotation-driven />,把相应⽅法封装于⼀个事务之中。
这听起来好像很简单。
但是,所有这些都是通过Spring 的代理对象封装并环绕增强原来的被注解@Transactional的类来实现的,但这种做法只有当事务⽅法是public的、并且是被代理类外部调⽤的情况下才会正常⼯作(可以参看Spring 事务处理模型图就明⽩,否则代理对象⾃⼰调⽤⾃⼰就会绕过对它的环绕事务增强,其他切⾯增强也是⼀样)。
这就很不爽了,意味着你不能在XXService或XXController内部串联处理⼀些具各⾃独⽴的事务,例如在XXController调⽤handleRequestInternal。
解决的办法是使⽤全功能完整成熟的AspectJ织⼊。
AspectJ织⼊⽅式同样⽀持@Transactional (其他⾃定义注解也⾏^_^),同时能被织⼊到所有⽅法中(不只是public),并且在内不外部都可以。
AspectJ有三种⽅式织⼊事务代码a.编译时(CTW). 拥有所有需要的源代码b.运⾏时(LTW).c.字节码织⼊(BTW).没有织⼊⽬标的源代码(如只有jar)这⾥我们使⽤CTW的⽅式Xml代码1. <beans xmlns="/schema/beans" xmlns:aop="/schema/aop">2.3. <aop:spring-configured>4.5. <bean id="annotationTransactionAspect" factory-method="aspectOf" class="org.springframework.transaction.aspectj.AnnotationTransactionAspect">6. <property name="transactionManager" ref="transactionManager"></property>7. </bean>8.9. <!-- the rest of your application here -->10. </beans>上⾯就是所有让Spring 使⽤Aspectj ⽅式@Transactional 注解事务的所有配置了。
beannameautoproxycreator 用法
beannameautoproxycreator 用法BeanNameAutoProxyCreator是Spring框架中的一个AOP(面向切面编程)代理创建器,它可以根据Bean的名称自动创建代理对象。
在本文中,我将详细介绍BeanNameAutoProxyCreator的用法,并提供一些示例来说明其功能和用途。
1. BeanNameAutoProxyCreator概述BeanNameAutoProxyCreator是一个BeanPostProcessor(Bean后置处理器),它在Spring容器初始化过程中对Bean进行处理。
它可以根据指定的Bean名称和拦截器来创建代理对象,并将代理对象替换原始的Bean对象。
2. 使用BeanNameAutoProxyCreator的步骤使用BeanNameAutoProxyCreator需要以下几个步骤:2.1 创建BeanNameAutoProxyCreator对象首先,我们需要在Spring配置文件中创建一个BeanNameAutoProxyCreator 对象。
可以使用<bean>标签来定义它,并设置相关属性。
例如:xml<bean id="beanNameAutoProxyCreator"class="org.springframework.aop.framework.autoproxy.BeanNameAutoP roxyCreator"><property name="beanNames"><list><value>bean1</value><value>bean2</value></list></property><property name="interceptorNames"><list><value>interceptor1</value><value>interceptor2</value></list></property></bean>在上面的示例中,我们创建了一个名为beanNameAutoProxyCreator的BeanNameAutoProxyCreator对象,并设置了两个属性:beanNames和interceptorNames。
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(试图“刷新”)。
Java动态代理四种实现方式详解
Java动态代理四种实现⽅式详解代理模式也是⼀种⾮常常见的设计模式。
了解Spring框架的都知道,Spring AOP 使⽤的就是动态代理模式。
今天就来系统的重温⼀遍代理模式。
在现实⽣活中代理是随处可见的,当事⼈因某些隐私不⽅便出⾯,或者当事⼈不具备某些相关的专业技能,⽽需要⼀个职业⼈员来完成⼀些专业的操作,也可能由于当事⼈没有时间处理事务,⽽聘⽤代理⼈出⾯。
⽽在软件设计中,使⽤代理模式的地⽅也很多,由于安全原因,屏蔽客户端直接访问真实对象,或者为了提升系统性能,使⽤代理模式实现延迟加载,还有就是AOP,对委托类的功能进⾏增强等。
⼀、代理模式的结构代理模式的主要参与者有4个,如下图所⽰:⾓⾊作⽤Subject主题接⼝,定义了代理类和委托类的公共对外⽅法,也是代理类代理委托类的⽅法RealSubject委托类,真实主题,真正实现业务逻辑的类Proxy代理类,代理和封装委托类Client客户端,使⽤代理类和主题接⼝完成业务逻辑loading="lazy" alt="" />⾓⾊作⽤Subject主题接⼝,定义了代理类和委托类的公共对外⽅法,也是代理类代理委托类的⽅法RealSubject委托类,真实主题,真正实现业务逻辑的类Proxy代理类,代理和封装委托类Client客户端,使⽤代理类和主题接⼝完成业务逻辑⼆、代理模式的实现代理模式⼀般分为静态代理和动态代理两种:静态代理,顾名思义,就是提前创建好代理类⽂件并在程序运⾏前已经编译成字节码。
动态代理,是指在运⾏时动态⽣成代理类,即代理类的字节码将在运⾏时⽣成并载⼊到ClassLoader中。
了解了两种代理模式⼤概区别后,接下来就以⼀个短信发送功能增强的⽰例来详细阐述两种代理的实现⽅式。
1、静态代理实现第⼀步,定义主题接⼝,该接⼝只有⼀个send⽅法:public interface ISender {public boolean send();}第⼆步,定义主题真正实现类:public class SmsSender implements ISender {public boolean send() {System.out.println("sending msg");return true;}}第三步,创建代理类,封装实现类:public class ProxySender implements ISender {private ISender sender;public ProxySender(ISender sender){this.sender = sender;}public boolean send() {System.out.println("处理前");boolean result = sender.send();System.out.println("处理后");return result;}}第四步,客户端调⽤:@Testpublic void testStaticProxy(){ISender sender = new ProxySender(new SmsSender());boolean result = sender.send();System.out.println("输出结果:" + result);}以上就实现了⼀个简单的静态代理,很明显,静态代理需要为每个真实主题定义⼀个形式上完全⼀样的封装类,如果真实主题⽅法有所修改,那代理类也需要跟着修改,不利于系统的维护。
defaultadvisorautoproxycreator使用
DefaultAdvisorAutoProxyCreator是Spring AOP(面向切面编程)内置的一个自动代理创建器(APC)。
在Spring容器中,每个Bean的初始化阶段,DefaultAdvisorAutoProxyCreator会查找所有的Spring Advisor Bean,并检测这些Advisor Bean是否需要包裹到正在初始化的Bean上。
这个过程中,DefaultAdvisorAutoProxyCreator只考虑容器中匹配的Spring Advisors,而不考虑其他方式定义的aspects。
使用DefaultAdvisorAutoProxyCreator对容器内所有Bean定义对应的对象进行自动代理之后,从容器中取得的对象实例就已经包含了织入的横切逻辑的代理对象,除非该对象不符合Pointcut规定的拦截条件。
需要注意的是,只有Advisor才既有Pointcut信息以捕捉符合条件的目标对象,又有相应的Advice。
在具体应用中,DefaultAdvisorAutoProxyCreator的配置方式与BeanNameAutoProxyCreator自动创建代理的方式非常相似,都是使用Bean后处理器为目标Bean创建实物代理。
不同的是,前者使用Advisor创建代理,而后者需要使用事务拦截器创建代理。
此外,DefaultAdvisorAutoProxyCreator实现了BeanProcessor接口。
当ApplicationContext读入所有的Bean配置信息后,这个类会扫描上下文,寻找所有的Advisor(一个Advisor是一个切入点和一个通知的组成),并将这些Advisor应用到所有符合切入点的Bean中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
spring 同时支持编程事务策略和声明式事务策略,大部分时候,都推荐使用声明式事务策略,使用声明式事务策略的优势十分明显。
对于使用声明式事务策略,可以使用TransactionProxyFactoryBean来配置事务代理Bean。
正如它的类名所暗示的,它是一个工厂Bean,工厂Bean用于生成一系列的Bean实例,这一系列的Bean实例都是Proxy.这种事务代理正是基于Spring AOP组件。
配置TransactionProxyFactoryBean时,一样需要指定目标Bean.
每个TransactionProxyFactoryBean为一个目标Bean生成事务代理,事务代理的方法改写了目标Bean的方法,就是在目标Bean的方法执行之前加入了事务,在目标Bean的方法正常结束之前提交事务,如查遇到了异常则回滚事务。
TransactionProxyFactoryBean创建事务代理时,需要了解当前事务所处的环境,该环境属性通过PlatformTransactionManager实例传入,而相关事务传入规则在TransactionProxyFactoryBean的定义中给出.
<!-- 配置事务拦截器Bean -->
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterce ptor">
<!-- 为事务拦截器bean注入一个事物管理器 -->
<property name="transactionManager" ref="transactionManager"></property>
<property name="transactionAttributes">
<!-- 定义事务传播属性 -->
<props>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="modify*">PROPAGATION_REQUIRED</prop>
<prop key="set*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 为bean创建事务代理 -->
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyC reator">
<!-- 指定满足哪些bean自动生成业务代理 -->
<property name="beanNames">
<!-- 需要自动创建事务代理的bean -->
<list>
<value>*0*IF</value>
</list>
<!-- 其它需要自动创建事务代理的bean -->
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
<!-- 可增加其它的interceptor -->
</list>
</property>
</bean>
<!-- hibernate 事务配置-->
<!-- 所有符合条件的方法将被放在事务中执行.方法的配置可以是正则表达式,如下的:创建,添加,删除,更新-->
<bean id="daoTransactionFactory" lazy-init="false"
class="org.springframework.transaction.interceptor.TransactionProxyFa ctoryBean"
abstract="true">
<property name="transactionManager">
<ref local="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>。