SpringBoot 注解事务声明式事务的方式

网友投稿 332 2023-04-10


SpringBoot 注解事务声明式事务的方式

springboot 对新人来说可能上手比springmvc要快,但是对于各位从springmvc转战到springboot的话,有些地方还需要适应下,尤其是xml配置。我个人是比较喜欢注解➕xml是因为看着方便,查找方便,清晰明了。但是xml完全可以使用注解代替,今天就扒一扒springboot中事务使用注解的玩法。

springboot的事务也主要分为两大类,一是xml声明式事务,二是注解事务,注解事务也可以实现类似声明式事务的方法,关于注解声明式事务,目前网上搜索不到合适的资料,所以在这里,我将自己查找和总结的几个方法写到这里,大家共同探讨

springboot 之 xml事务

可以使用 @ImportResource("classpath:transaction.xml") 引入该xml的配置,xml的配置如下

xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:aop="http://springframework.org/schema/aop"

xmlns:tx="http://springframework.org/schema/tx"

xsi:schemaLocation="

http://springframework.org/schema/beans

http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/tx

http://springframework.org/schema/tx/spring-tx.xsd

http://springframework.org/schema/aop

http://springframework.org/schema/aop/spring-aop.xsd">

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:aop="http://springframework.org/schema/aop"

xmlns:tx="http://springframework.org/schema/tx"

xsi:schemaLocation="

http://springframework.org/schema/beans

http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/tx

http://springframework.org/schema/tx/spring-tx.xsd

http://springframework.org/schema/aop

http://springframework.org/schema/aop/spring-aop.xsd">

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

springboot 启动类如下:

package com.example.fm;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.ImportResource;

@ImportResource("classpath:transaction.xml")

@SpringBootApplication

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

}

启动后即可开启事务,不过项目里导入了xml配置,如果不想导入xml配置,可以使用注解的方式。

springboot 之 注解事务

注解事务讲解之前,需要先了解下spring创建代理的几个类,在spring内部,是通过BeanPostProcessor来完成自动创建代理工作的。BeanPostProcessor接口的实现只是在ApplicationContext初始化的时候才会自动加载,而普通的BeanFactory只能通过编程的方式调用之。根据  匹配规则的不同大致分为三种类别:

a、匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameAutoProxyCreator

*Service

testInterceptor

b、根据Bean中的AspectJ注解自动创建代理,实现类AnnotationAwareAspectJAutoProxyCreator

c、根据Advisor的匹配机制自动创建代理,会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类DefaultAdvisorAutoProxyCreator

接下来开讲注解开启事务的方法:

1、Transactional注解事务

需要在进行事物管理的方法上添加注解@Transactional,或者偷懒的话直接在类上面添加该注解,使得所有的方法都进行事物的管理,但是依然需要在需要事务管理的类上都添加,工作量比较大,这里只是简单说下,具体的可以google或者bing

2、注解声明式事务

Component或Configuration中bean的区别,有时间我会专门写一篇来讲解下

a.方式1,这里使用Component或Configuration事务都可以生效

package com.exmple.service.fm9.config;

import java.util.Collections;

import java.util.HashMap;

import java.util.Map;

import org.aspectj.lang.annotation.Aspect;

import org.springframework.aop.Advisor;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;

import org.springframework.aop.support.DefaultPointcutAdvisor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.stereotype.Component;

import org.springframework.transaction.PlatformTransactionManager;

import org.springframework.transaction.TransactionDefinition;

import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;

import org.springframework.transaction.interceptor.RollbackRuleAttribute;

import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;

import org.springframework.transaction.interceptor.TransactionAttribute;

import org.springframework.transaction.interceptor.TransactionInterceptor;

/**

* Created by guozp on 2017/8/28.

*/

@Aspect

//@Component 事务依然生效

@Configuration

public class TxAdviceInterceptor {

private static final int TX_METHOD_TIMEOUT = 5;

private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.alibaba.fm9..service.*.*(..))";

@Autowired

private PlatformTransactionManager transactionManager;

@Bean

public TransactionInterceptor txAdvice() {

NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

/*只读事务,不做更新操作*/

RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();

readOnlyTx.setReadOnly(true);

readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );

/*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/

RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();

requiredTx.setRollbackRules(

Collections.singletonList(new RollbackRuleAttribute(Exception.class)));

requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

requiredTx.setTimeout(TX_METHOD_TIMEOUT);

Map txMap = new HashMap<>();

txMap.put("add*", requiredTx);

txMap.put("save*", requiredTx);

txMap.put("insert*", requiredTx);

txMap.put("update*", requiredTx);

txMap.put("delete*", requiredTx);

txMap.put("get*", readOnlyTx);

txMap.put("query*", readOnlyTx);

source.setNameMap( txMap );

TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);

return txAdvice;

}

@Bean

public Advisor txAdviceAdvisor() {

AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

pointcut.setExpression(AOP_POINTCUT_EXPRESSION);

return new DefaultPointcutAdvisor(pointcut, txAdvice());

//return new DefaultPointcutAdvisor(pointcut, txAdvice);

}

}

b.方式1,这里使用Component或Configuration事务都可以生效

package com.exmple.service.fm9.config;

import java.util.Collections;

import java.util.HashMap;

import java.util.Map;

import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.stereotype.Component;

import org.springframework.transaction.PlatformTransactionManager;

import org.springframework.transaction.TransactionDefinition;

import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;

import org.springframework.transaction.interceptor.RollbackRuleAttribute;

import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;

import org.springframework.transaction.interceptor.TransactionAttribute;

import org.springframework.transaction.interceptor.TransactionAttributeSource;

import org.springframework.transaction.interceptor.TransactionInterceptor;

/**

* Created by guozp on 2017/8/29.

*/

//@Component 事务依然生效

@Configuration

public class TxAnoConfig {

/*事务拦截类型*/

@Bean("txSource")

public TransactionAttributeSource transactionAttributeSource(){

NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

/*只读事务,不做更新操作*/

RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();

readOnlyTx.setReadOnly(true);

readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );

/*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/

//RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();

//requiredTx.setRollbackRules(

// Collections.singletonList(new RollbackRuleAttribute(Exception.class)));

//requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED,

Collections.singletonList(new RollbackRuleAttribute(Exception.class)));

requiredTx.setTimeout(5);

Map txMap = new HashMap<>();

txMap.put("add*", requiredTx);

txMap.put("save*", requiredTx);

txMap.put("insert*", requiredTx);

txMap.put("update*", requiredTx);

txMap.put("delete*", requiredTx);

txMap.put("get*", readOnlyTx);

txMap.put("query*", readOnlyTx);

source.setNameMap( txMap );

return source;

}

/**切面拦截规则 参数会自动从容器中注入*/

@Bean

public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor){

AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();

pointcutAdvisor.setAdvice(txInterceptor);

pointcutAdvisor.setExpression("execution (* com.alibaba.fm9..service.*.*(..))");

return pointcutAdvisor;

}

/*事务拦截器*/

@Bean("txInterceptor")

TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx){

return new TransactionInterceptor(tx , transactionAttributeSource()) ;

}

}

c.方式1,这里使用Component或Configuration事务都可以生效

package com.exmple.service.fm9.config;

import java.util.Properties;

import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import org.springframework.stereotype.Component;

import org.springframework.transaction.interceptor.TransactionInterceptor;

/**

* Created by guozp on 2017/8/28.

*

*/

//@Component

@Configuration

public class TxConfigBeanName {

@Autowired

private DataSourceTransactionManager transactionManager;

// 创建事务通知

@Bean(name = "txAdvice")

public TransactionInterceptor getAdvisor() throws Exception {

Properties properties = new Properties();

properties.setProperty("get*", "PROPAGATION_REQUIREDktrEAw,-Exception,readOnly");

properties.setProperty("add*", "PROPAGATION_REQUIRED,-Exception,readOnly");

properties.setProperty("save*", "PROPAGATION_REQUIRED,-Exception,readOnly");

properties.setProperty("update*", "PROPAGATION_REQUIRED,-Exception,readOnly");

properties.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception,readOnly");

TransactionInterceptor tsi = new TransactionInterceptor(transactionManager,properties);

return tsi;

}

@Bean

public BeanNameAutoProxyCreator txProxy() {

BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();

creator.setInterceptorNames("txAdvice");

creator.setBeanNames("*Service", "*ServiceImpl");

creator.setProxyTargetClass(true);

return creator;

}

}

d.方式1,这里使用Component或Configuration并不是所有事务都可以生效,例如Configuration的时候如果打开注释部分的而且不把代码都移动到 defaultPointcutAdvisor(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。

ackage com.alibaba.fm9.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;

import org.springframework.aop.support.DefaultPointcutAdvisor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import org.springframework.stereotype.Component;

import org.springframework.transaction.PlatformTransactionManager;

import org.springframework.transaction.interceptor.TransactionInterceptor;

/**

* Created by guozp on 2017/8/28.

* ???????

*/

@Configuration //事务失效,都移动到一个方法不失效

//@Component // 事务可行,不用都移动到一个方法

public class TxOtherConfigDefaultBean {

public static final String transactionExecution = "execution (* com.alibaba.fm9..service.*.*(..))";

@Autowired

private PlatformTransactionManager transactionManager;

//@Bean

//@ConditionalOnMissingBean

//public PlatformTransactionManager transactionManager() {

// return new DataSourceTransactionManager(dataSource);

//}

@Bean

public TransactionInterceptor transactionInterceptor() {

Properties attributes = new Properties();

attributes.setProperty("get*", "PROPAGATION_REQUIRED,-Exception");

attributes.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");

attributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");

attributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");

//TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager(), attributes);

TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);

return txAdvice;

}

//@Bean

//public AspectJExpressionPointcut aspectJExpressionPointcut(){

// AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

// pointcut.setExpression(transactionExecution);

// return pointcut;

//}

@Bean

public DefaultPointcutAdvisor defaultPointcutAdvisor(){

//AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

//pointcut.setExpression(transactionExecution);

//DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();

//advisor.setPointcut(pointcut);

//advisor.setAdvice(transactionInterceptor());

AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

pointcut.setExpression(transactionExecution);

DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();

advisor.setPointcut(pointcut);

Properties attributes = new Properties();

attributes.setProperty("get*", "PROPAGATION_REQUIRED,-Exception");

attributes.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");

attributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");

attributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");

TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);

advisor.setAdvice(txAdvice);

return advisor;

}

}

简单来说,springboot使用上述注解的几种方式开启事物,可以达到和xml中声明的同样效果,但是却告别了xml,使你的代码远离配置文件。

总结

以上所述是给大家介绍的SpringBoot 注解事务声明式事务的方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:ionic2懒加载配置详解
下一篇:JAVA正则表达式过滤文件的实现方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~