前言
对于数据库的操作,可能存在脏读、不可重复读、幻读等问题,从而引入了事务的概念。
事务
1.1 事务的定义
事务是指在数据库管理系统中,一系列紧密相关的操作序列,这些操作作为一个单一的工作单元执行。事务的特点是要么全部成功,要么全部失败,不会出现部分完成的情况。如果事务中的任何一个操作失败,那么整个事务都会被回滚到开始之前的状态,以确保数据库的一致性和完整性。
1.2 事务的特性
事务具有4个特性:原子性、一致性、隔离性和持久性。通常称为ACID。
1)原子性(Atomicity)
事务是一个不可分割的工作单位,事务中包含的所有操作要么全部成功,要么全部失败。
2)隔离性(Isolation)
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的。
3)持久性(Durability)
一旦事务提交成功,则其所做的修改就会永久保存在数据库中,即使发生系统故障也不会丢失。
4)一致性(Consistency)
事务必须确保数据库从一个一致性状态转变到另一个一致性状态。
更准确的说,事务是通过原子性、隔离性和持久性,实现了事务的一致性。另外,一致性还需要额外的工作来保证,如转账,从A转给B,A的资金减少了,B的资金增加了。转账要么成功、要么失败,但不管成功还是失败,事务的一致性要求两人的资金之和必须一致,要么成功,A减少了、B增加了,要么失败,A和B的资金都不变。为了一致性,需要程序来开启事务,同时修改A和B的资金,从而才能保证一致性。
SpringBoot自动装载
在SpringBoot框架中,会自动引入TransactionAutoConfiguration。且在META-INF的spring-autoconfigure-metadata.properties有如下配置:
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration=
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration=
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration.ConditionalOnBean=org.springframework.transaction.TransactionManager
说明在自动引入TransactionAutoConfiguration时,必须存在TransactionManager的bean,且要先引入内部类EnableTransactionManagementConfiguration。
EnableTransactionManagementConfiguration
内部类EnableTransactionManagementConfiguration的源码如下:
public class TransactionAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
}
EnableTransactionManagementConfiguration内中会自动引入JdkDynamicAutoProxyConfiguration和CglibAutoProxyConfiguration,且添加了@EnableTransactionManagement注解。该注解会自动引入TransactionManagementConfigurationSelector。TransactionManagementConfigurationSelector的父类实现了ImportSelector接口,该类的selectImports()方法返回AutoProxyRegistrar和ProxyTransactionManagementConfiguration类名数组,即AutoProxyRegistrar和ProxyTransactionManagementConfiguration会自动注入到Spring IOC容器中。
Spring的配置类解析的时候,会执行ConfigurationClassParser.processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, boolean checkForCircularImports),在该方法中,判断importCandidates是否继承于ImportSelector接口,如果是,调用ImportSelector的selectImports()方法,获取需要额外自动加入容器的类。
ProxyTransactionManagementConfiguration
ProxyTransactionManagementConfiguration的源码如下:
package org.springframework.transaction.annotation;
/**
* Transaction事务管理代理的配置类
*/
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**
* 返回一个BeanFactoryTransactionAttributeSourceAdvisor【继承AbstractBeanFactoryPointcutAdvisor,重
* 写了getPointcut()方法。即当前Advisor包含了事务需要的advice以及pointcut】
* @return
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
// 声明一个BeanFactoryTransactionAttributeSourceAdvisor对象,
// 传入的transactionAttributeSource为AnnotationTransactionAttributeSource
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
/**
* 创建一个AnnotationTransactionAttributeSource对象,该继承AbstractFallbackTransactionAttributeSource,
* 对外提供了getTransactionAttribute()方法。该方法返回某个方法的事务注解信息
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
/**
* 创建一个TransactionInterceptor对象
* @return
*/
@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;
}
}
在ProxyTransactionManagementConfiguration中,自动注入了BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource和TransactionInterceptor。添加了事务处理的advisor,该advisor生效时,会执行TransactionInterceptor拦截器。
BeanFactoryTransactionAttributeSourceAdvisor
BeanFactoryTransactionAttributeSourceAdvisor的源码如下:
package org.springframework.transaction.interceptor;
/**
* 继承AbstractBeanFactoryPointcutAdvisor,重写了getPointcut()方法。即当前Advisor包含了事务需要的advice以及pointcut
* 1、维护TransactionAttributeSource对象;
* 2、创建一个TransactionAttributeSourcePointcut,重写getTransactionAttributeSource(),返回TransactionAttributeSource对
* 象给TransactionAttributeSourcePointcut,进行方法事务注解判断
*/
@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
// 在ProxyTransactionManagementConfiguration类中的transactionAdvisor()方法,
// 设置transactionAttributeSource为AnnotationTransactionAttributeSource
@Nullable
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
在BeanFactoryTransactionAttributeSourceAdvisor切面中,切点为自定义的实现抽象类TransactionAttributeSourcePointcut的对象,抽象方法getTransactionAttributeSource()返回的TransactionAttributeSource对象为ProxyTransactionManagementConfiguration的transactionAdvisor()方法传入的AnnotationTransactionAttributeSource对象。
TransactionAttributeSourcePointcut
TransactionAttributeSourcePointcut的源码如下:
package org.springframework.transaction.interceptor;
/**
* 抽象类,继承StaticMethodMatcherPointcut,属于静态的方法匹配。在方法匹配中,通过抽象方法getTransactionAttributeSource()获
* 取TransactionAttributeSource对象,然后执行TransactionAttributeSource.getTransactionAttribute(),判断方法是否有事务注解,
* 如果有,表示匹配;没有则不匹配
*/
@SuppressWarnings("serial")
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
// 返回AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
// 在AnnotationTransactionAttributeSource的getTransactionAttribute()方法中,
// 获取方法添加的@Transactional注解的信息,如果没有添加@Transactional注解,返回null
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof TransactionAttributeSourcePointcut)) {
return false;
}
TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;
return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());
}
@Override
public int hashCode() {
return TransactionAttributeSourcePointcut.class.hashCode();
}
@Override
public String toString() {
return getClass().getName() + ": " + getTransactionAttributeSource();
}
/**
* 抽象方法,获得一个TransactionAttributeSource对象
* @return
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
}
TransactionAttributeSourcePointcut继承StaticMethodMatcherPointcut,StaticMethodMatcherPointcut的类匹配默认为ClassFilter.TRUE,即匹配所有的类。
当Spring中的bean对象声明之后,都会调用BeanFactoryTransactionAttributeSourceAdvisor切面,遍历bean的方法,执行切点的matches(Method method, @Nullable Class<?> targetClass)方法,该方法执行如下:
6.1)调用getTransactionAttributeSource(),获取一个TransactionAttributeSource。此处为AnnotationTransactionAttributeSource对象;
6.2)因为TransactionAttributeSource对象不为空,所以执行TransactionAttributeSource的getTransactionAttribute()方法,该方法会执行AnnotationTransactionAttributeSource的父类AbstractFallbackTransactionAttributeSource的getTransactionAttribute()方法,如果方法有返回值,则matches()方法返回true。对应的bean创建代理类,并添加Advisor中的拦截器,即添加TransactionInterceptor;
在该方法中,最终会调用子类AnnotationTransactionAttributeSource的determineTransactionAttribute()方法,遍历事务的解析器,从解析器中获取事务属性信息;结合1)中的描述,会解析org.springframework.transaction.annotation包和javax.transaction包下的@Transactional注解。如果没有@Transactional注解,getTransactionAttribute()最终返回null。matches()会返回false,即不支持,如果有注解,则返回true。对应的bean创建代理类,并添加Advisor中的拦截器,即添加TransactionInterceptor;
AnnotationTransactionAttributeSource
AnnotationTransactionAttributeSource的相关源码如下:
package org.springframework.transaction.annotation;
/**
* 继承AbstractFallbackTransactionAttributeSource,对外提供了getTransactionAttribute()方法。该方法返回某个方法的事务注解信息
* 1、添加不同类型的事务注解解析器,用于解析注解信息。支撑jta、ejb和spring的事务
*/
@SuppressWarnings("serial")
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
/** 判断包中是否有javax.transaction.Transactional这个类,即项目中是否有对应的包。如果有,则需要添加对应的事务解析器 */
private static final boolean jta12Present = ClassUtils.isPresent(
"javax.transaction.Transactional", AnnotationTransactionAttributeSource.class.getClassLoader());
/** 判断包中是否有javax.ejb.TransactionAttribute这个类,即项目中是否有对应的包。如果有,则需要添加对应的事务解析器 */
private static final boolean ejb3Present = ClassUtils.isPresent(
"javax.ejb.TransactionAttribute", AnnotationTransactionAttributeSource.class.getClassLoader());
/** 标记是否只有public方法才可以添加事务,默认为true */
private final boolean publicMethodsOnly;
private final Set<TransactionAnnotationParser> annotationParsers;
public AnnotationTransactionAttributeSource() {
this(true);
}
/**
* 设置publicMethodsOnly的值,并添加事务的注解解析器集合
*/
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
if (jta12Present || ejb3Present) {
this.annotationParsers = new LinkedHashSet<>(4);
// 添加spring的Transactional注解解析器
this.annotationParsers.add(new SpringTransactionAnnotationParser());
// 根据条件,添加jta和ejb3两种事务的注解解析器
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
else {
// 如果不支持jta和ejb3两种注解的事务,则只添加spring的Transactional注解解析器
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
/**
* 调用determineTransactionAttribute()方法,从类中查找事务注解信息
*/
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
/**
* 调用determineTransactionAttribute()方法,从方法中查找事务注解信息
*/
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
/**
* 确定事务属性。遍历事务解析器集合,对当前element进行解析,如果能够正常解析,则返回对应
* 的TransactionAttribute【RuleBasedTransactionAttribute对象】;否则返回null
*/
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
}
在AnnotationTransactionAttributeSource构造方法中,会添加SpringTransactionAnnotationParser和JtaTransactionAnnotationParser事务注解解析器。
7.1 SpringTransactionAnnotationParser
SpringTransactionAnnotationParser的源码如下:
package org.springframework.transaction.annotation;
/**
* 实现TransactionAnnotationParser,解析org.springframework.transaction.annotation.Transactional的注解信息,
* 返回一个RuleBasedTransactionAttribute对象
*/
@SuppressWarnings("serial")
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
/**
* 解析@Transaction注解,获取一个TransactionAttribute对象
*/
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 在所提供的element上方的注释层次结构中查找Transactional的第一个注释,
// 并将该注释的属性与注释层次结构较低级别注释中的匹配的attribute合并
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
// 解析Transactional注解,返回一个RuleBasedTransactionAttribute对象
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
}
/**
* 从注解属性对象中,获取事务注解相关属性信息,封装成RuleBasedTransactionAttribute对象
*/
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
// 根据注解的信息,创建一个RuleBasedTransactionAttribute对象
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"));
// 添加回滚规则
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
@Override
public boolean equals(Object other) {
return (this == other || other instanceof SpringTransactionAnnotationParser);
}
@Override
public int hashCode() {
return SpringTransactionAnnotationParser.class.hashCode();
}
}
SpringTransactionAnnotationParser用于解析org.springframework.transaction.annotation包下的@Transactional的注解信息。
7.2 JtaTransactionAnnotationParser
JtaTransactionAnnotationParser的源码如下:
package org.springframework.transaction.annotation;
/**
* 实现TransactionAnnotationParser,用于解析javax.transaction.Transactional注解的事务属性。返回一个RuleBasedTransactionAttribute对象
*/
@SuppressWarnings("serial")
public class JtaTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
/**
* 判断是否有javax.transaction.Transactional,如果有,则进行注解解析【解析传播行为,回滚的异常类、不回滚的异常类设置回滚规则】,
* 返回一个RuleBasedTransactionAttribute对象
* @param element
* @return
*/
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
element, javax.transaction.Transactional.class);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
public TransactionAttribute parseTransactionAnnotation(javax.transaction.Transactional ann) {
return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
}
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
// 通过注解的value设定传播行为。默认为REQUIRED
rbta.setPropagationBehaviorName(
RuleBasedTransactionAttribute.PREFIX_PROPAGATION + attributes.getEnum("value").toString());
// 根据设置的回滚的异常类,添加回滚规则
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackOn")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
// 根据设置的不回滚的异常类,添加回滚规则,定义为不回滚
for (Class<?> rbRule : attributes.getClassArray("dontRollbackOn")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
@Override
public boolean equals(Object other) {
return (this == other || other instanceof JtaTransactionAnnotationParser);
}
@Override
public int hashCode() {
return JtaTransactionAnnotationParser.class.hashCode();
}
}
JtaTransactionAnnotationParser用于解析javax.transaction包下的@Transactional注解。
在6.2)中调用AnnotationTransactionAttributeSource的getTransactionAttribute(),最终会调用AnnotationTransactionAttributeSource的determineTransactionAttribute()方法,遍历事务注解的解析器,从解析器中获取事务属性信息。只要方法中添加了org.springframework.transaction.annotation包或javax.transaction包的@Transactional注解,则能够正常获取事务属性信息。
小结
限于篇幅,本篇先分享到这里。以下做一个小结:
1)在SpringBoot框架的项目,项目启动时,会自动开启@EnableTransactionManagement注解,从而自动添加BeanFactoryTransactionAttributeSourceAdvisor切面,添加TransactionAttributeSourcePointcut切点。该切点的ClassFilter为ClassFilter.TRUE,即过滤所有的类。
2)Spring的bean自动注入时,会执行BeanFactoryTransactionAttributeSourceAdvisor切面,遍历bena的方法,执行TransactionAttributeSourcePointcut的matches()。在该方法中,会执行AnnotationTransactionAttributeSource的getTransactionAttribute()方法,判断方法是否添加了org.springframework.transaction.annotation包或javax.transaction包下的@Transactional注解,如果有,则bean的代理类中添加TransactionInterceptor拦截器;
关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。