springboot的事务也主要分为两大类,一是xml声明式事务,二是注解事务.
可以使用 @ImportResource("classpath:transaction.xml")
引入该xml的配置,xml的配置如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop=
"http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans
http:
//www.springframework.org/schema/beans/spring-beans.xsd
http:
//www.springframework.org/schema/tx
http:
//www.springframework.org/schema/tx/spring-tx.xsd
http:
//www.springframework.org/schema/aop
http:
//www.springframework.org/schema/aop/spring-aop.xsd">
<bean id=
"txManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
<property name=
"dataSource"
ref=
"dataSource"
></property>
</bean>
<tx:advice id=
"cftxAdvice"
transaction-manager=
"txManager"
>
<tx:attributes>
<tx:method name=
"query*"
propagation=
"SUPPORTS"
read-only=
"true"
></tx:method>
<tx:method name=
"get*"
propagation=
"SUPPORTS"
read-only=
"true"
></tx:method>
<tx:method name=
"select*"
propagation=
"SUPPORTS"
read-only=
"true"
></tx:method>
<tx:method name=
"*"
propagation=
"REQUIRED"
rollback-
for
=
"Exception"
></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id=
"allManagerMethod"
expression=
"execution (* com.exmaple.fm..service.*.*(..))"
/>
<aop:advisor advice-ref=
"txAdvice"
pointcut-ref=
"allManagerMethod"
order=
"0"
/>
</aop:config>
</beans>
|
springboot 启动类如下:
1
2
3
4
5
6
7
8
9
10
11
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<bean id=
"testInterceptor"
class
="com.example.service.config.testInerceptor”></bean>
<bean id=
"profileAutoProxyCreator"
class
="org.springframework.aop.framework.
autoproxy.BeanNameAutoProxyProxyCreator">
<bean>
<property name=
"beanNames"
>
<list>
<value>*Service</value>
</list>
</property>
<property name=
"interceptorNames"
>
<value> testInterceptor </value>
</property>
</bean>
|
b、根据Bean中的AspectJ注解自动创建代理,实现类AnnotationAwareAspectJAutoProxyCreator
1
2
3
4
5
6
7
|
<aop:aspectj-autoproxy proxy-target-
class
=
"true"
/>
<bean id=
"annotationAwareAspectJAutoProxyCreatorTest"
class
=
"com.example.service.AnnotationAwareAspectJAutoProxyCreatorTest"
/>
<aop:config>
<aop:aspect ref=
"annotationAwareAspectJAutoProxyCreatorTest"
>
<aop:around method=
"process"
pointcut=
"execution (* com.example.service.fm..*.*(..))"
/>
</aop:aspect>
</aop:config>
|
c、根据Advisor的匹配机制自动创建代理,会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类DefaultAdvisorAutoProxyCreator
接下来开讲注解开启事务的方法:
1、Transactional注解事务
需要在进行事物管理的方法上添加注解@Transactional,或者偷懒的话直接在类上面添加该注解,使得所有的方法都进行事物的管理,但是依然需要在需要事务管理的类上都添加,工作量比较大,这里只是简单说下,具体的可以google或者bing
2、注解声明式事务
Component或Configuration中bean的区别,有时间我会专门写一篇来讲解下
a.方式1,这里使用Component或Configuration事务都可以生效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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<String, TransactionAttribute> 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事务都可以生效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
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<String, TransactionAttribute> 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事务都可以生效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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_REQUIRED,-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(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
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 注解事务声明式事务的方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!