1、事务的基本知识点:
1.1、事务的特性:
A(原子性 Automic)
C(一致性 Consistency)
I(隔离性 Isolation)
D(持久性 Duration)
1.2、数据并发问题
1、脏读:A事务读取B事务尚未提交的更改数据。
2、不可重复读:同一个事务中,多次查询,可能查询到的值是不一样的。
3、幻读:A事务读取到了B事务新增的数据。
4、第一类数据丢失:A事务撤销的时候,把已提交事务的B事务的更新数据覆盖。
5、第二类更新丢失:A事务覆盖B事务已经提交的数据。
1.3、事务隔离级别
隔离级别 |
脏读 |
幻读 |
不可重复读 |
第一类丢失更新 |
第二类丢失更新 |
READ_UNCOMMITED |
会 |
会 |
会 |
不会 |
会 |
READ_COMMITED |
不会 |
会 |
会 |
不会 |
会 |
REPEATABLE READ |
不会 |
不会 |
会 |
不会 |
不会 |
SERIALIZABLE |
不会 |
不会 |
不会 |
不会 |
不会 |
2、Spring中事务的传播机制
3、Spring中基于xml声明事务
4、基于xml这种方式声明事务的原理分析
我们使用了 4.1、tx 命名空间的解析TxNameSpaceHandler其源码如下: 4.2、我们目前是使用了 我们先来看TxAdviceBeanDefinitionParser的类图: 我们要找的parse()方法在AbstractBeanDefinitionParser类中,其源码如下: AbstractSingleBeanDefinitionParser的parseInternal方法实现如下: 从AbstractSingleBeanDefinitionParser的parseInternal方法中我们知道是构建一个类型为TransactionInterceptor的BeanDefinition实例注册到IOC容器中。这个TransactionInterceptor其实就是Advice类型的增强,也就是提供事务的功能的增强。TransactionInterceptor的类图如下: 从类图中我们可以看出TransactionInterceptor继承了抽象类TransactionAspectSupport,TransactionAspectSupport里面提供了事务功能,比如TransactionAspectSupport的invokeWithinTransaction使用事务包围执行某方法,还有比如管理事务管理器的方法determineTransactionManager,提交事务的方法commitTransactionAfterReturning、事务回滚的方法completeTransactionAfterThrowing等。。。 TransactionAspectSupport的主要的成员属性有: 既然知道的TransactionAspectSupport组要这些属性那么是在什么时候进行设置的呢?也就是说transactionManager、transactionAttributeSource属性是在什么时候进行设置的呢?我们查看TxAdviceBeanDefinitionParser的 doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder)方法会有答案,其源码如下: 4.3、总结 TxAdviceBeanDefinitionParser做的事情就是构建一个beanClass=TransactionInterceptor.class的BeanDefinition实例注册到IOC容器中。在构建的过程会设置TransactionInterceptor的transactionManager属性的引用(RuntimeBeanReference),其次还会解析 TransactionAspectSupport的invokeWithinTransaction方法实现源码解析 createTransactionIfNecessary方法实现 AbstractPlatformTransactionManager中的getTransaction(TransactionDefinition definition)方法源码: 我们从上面的AbstractPlatformTransactionManager中的getTransaction(TransactionDefinition definition)方法中提及到了两个抽象方法一个是doGetTransaction()、另一个是doBegin(transaction, definition); 我们使用DataSourceTranscationManager来进行举例 1、doGetTransaction()源码: 2、doBegin(transaction, definition)源码: 到此整个基于xml声明事务的使用以及原理分析结束。 public class TxNamespaceHandler extends NamespaceHandlerSupport {
标签中用于指定事务管理器的参数名称用法
@Override
public final BeanDefinition parse(Element element, ParserContext parserContext) {
解析元素element从而得到一个BeanDefinition实例,此方法是抽象方法在子类
AbstractSingleBeanDefinitionParser中有实现,我们待会需要查看
AbstractSingleBeanDefinitionParser的parseInternal方法实现。
AbstractBeanDefinition definition = parseInternal(element, parserContext);
if (definition != null && !parserContext.isNested()) {
try {
String id = resolveId(element, definition, parserContext);
if (!StringUtils.hasText(id)) {
parserContext.getReaderContext().error(
"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
+ "' when used as a top-level tag", element);
}
String[] aliases = null;
if (shouldParseNameAsAliases()) {
String name = element.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(name)) {
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
}
}
使用上面解析到的BeanDefinition实例来构建一个BeanDefinitionHolder并注册到IOC容器中。
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
registerBeanDefinition(holder, parserContext.getRegistry());
if (shouldFireEvents()) {
BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
postProcessComponentDefinition(componentDefinition);
parserContext.registerComponent(componentDefinition);
}
}
catch (BeanDefinitionStoreException ex) {
parserContext.getReaderContext().error(ex.getMessage(), element);
return null;
}
}
return definition;
}
@Override
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
创建一个空的GenericBeanDefinition以及BeanDefinitionBuilder
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
String parentName = getParentName(element);
if (parentName != null) {
builder.getRawBeanDefinition().setParentName(parentName);
}
获取一个beanClass类型,这个在TxAdviceBeanDefinitionParser中实现了,且返回是一个TransactionInterceptor.class
Class> beanClass = getBeanClass(element);
if (beanClass != null) {
builder.getRawBeanDefinition().setBeanClass(beanClass);
}
else {
String beanClassName = getBeanClassName(element);
if (beanClassName != null) {
builder.getRawBeanDefinition().setBeanClassName(beanClassName);
}
}
builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
if (parserContext.isNested()) {
// Inner bean definition must receive same scope as containing bean.
builder.setScope(parserContext.getContainingBeanDefinition().getScope());
}
if (parserContext.isDefaultLazyInit()) {
// Default-lazy-init applies to custom bean definitions as well.
builder.setLazyInit(true);
}
做解析在TransactionInterceptor中实现了doParse方法。
doParse(element, parserContext, builder);
return builder.getBeanDefinition();
}
使用ThreadLocal绑定当前线程中的事务信息类TransactionInfo,我们可以显示的使用其获取事务信息
private static final ThreadLocal
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
此处传过来的builder中的BeanDefinition的beanClass是TransactionInterceptor.class
第一步给transactionManager属性添加一个引用,这个引用就是指定事务管理器,其实现就是让
transactionManager是一个RuntimeBeanReference(beanName),在TransactionInterceptor类
做依赖注入的时候会先实例化+初始化beanName=transactionManager的bean然后赋值给
transactionManager这个属性。
builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));
List
5、装配好的TransactionInterceptor实例如何提供事务
TransactionInterceptor既然实现了AOP联盟的MethodInterceptor接口,那就一定实现了invoke方法,因此我们的主要重点就是TransactionInterceptor类的public Object invoke(final MethodInvocation invocation) throws Throwable方法,其源码如下: public Object invoke(final MethodInvocation invocation) throws Throwable {
Class> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
调用父类TransactionAspectSupport的使用事务执行目标方法。
return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
protected Object invokeWithinTransaction(Method method, Class> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
使用之前构建的TransactionAttributeSource获取事务属性资源
final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
获取事务管理器
final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
Object result;
以我们比较熟悉的DataSourceTranscationManager举例,肯定是走else,请移步else
if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
final TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder();
try {
result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, new TransactionCallback
protected TransactionAspectSupport.TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
if (txAttr != null && ((TransactionAttribute)txAttr).getName() == null) {
txAttr = new DelegatingTransactionAttribute((TransactionAttribute)txAttr) {
public String getName() {
return joinpointIdentification;
}
};
}
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
使用事务管理器获取一个TransactionStatus实例,在
AbstractPlatformTransactionManager中会实现,下面我们会跟踪源码来解析原理。
status = tm.getTransaction((TransactionDefinition)txAttr);
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured");
}
}
准备事务信息TransactionInfo实例,在此处使用TransactionStatus实例构建一个TransactionInfo
实例,然后绑定到当前线程,就是使用TransactionAspectSupport中的transactionInfoHolder类型
是ThreadLocal。
return this.prepareTransactionInfo(tm, (TransactionAttribute)txAttr, joinpointIdentification, status);
}
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
获取一个事务对象,这个是一个抽象方法,由具体的事务管理器实现,我们以DataSourceTransactionManager举例说明,DataSourceTransactionManager返回的是一个类型为 DataSourceTransactionManager.DataSourceTransactionObject的内部类实例。
Object transaction = this.doGetTransaction();
boolean debugEnabled = this.logger.isDebugEnabled();
if (definition == null) {
definition = new DefaultTransactionDefinition();
}
if (this.isExistingTransaction(transaction)) {
如果当前目标方法已经在事务的环境中,那就执行存在事务的逻辑,比如根据事务的传播行为进行逻辑修改。
return this.handleExistingTransaction((TransactionDefinition)definition, transaction, debugEnabled);
} else if (((TransactionDefinition)definition).getTimeout() < -1) {
如果事务的超时时间配置为小于-1 那就直接抛出异常。
throw new InvalidTimeoutException("Invalid transaction timeout", ((TransactionDefinition)definition).getTimeout());
} else if (((TransactionDefinition)definition).getPropagationBehavior() == 2) {
如果事务的传播机制是2,也就是PROPAGATION_MANDATORY 必须在已经存在的事务中执行,走到这里说明肯定不是已经在事务中调用,那就直接抛出异常。
throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");
} else if (((TransactionDefinition)definition).getPropagationBehavior() != 0 && ((TransactionDefinition)definition).getPropagationBehavior() != 3 && ((TransactionDefinition)definition).getPropagationBehavior() != 6) {
if (((TransactionDefinition)definition).getIsolationLevel() != -1 && this.logger.isWarnEnabled()) {
this.logger.warn("Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = this.getTransactionSynchronization() == 0;
return this.prepareTransactionStatus((TransactionDefinition)definition, (Object)null, true, newSynchronization, debugEnabled, (Object)null);
} else {
AbstractPlatformTransactionManager.SuspendedResourcesHolder suspendedResources = this.suspend((Object)null);
if (debugEnabled) {
this.logger.debug("Creating new transaction with name [" + ((TransactionDefinition)definition).getName() + "]: " + definition);
}
如果是默认的PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED
try {
boolean newSynchronization = this.getTransactionSynchronization() != 2;
创建一个DefaultTransactionStatus 事务状态信息实例
DefaultTransactionStatus status = this.newTransactionStatus((TransactionDefinition)definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
开始事务是个抽象方法,我们会以DataSourceTransactionManager进行举例说明
this.doBegin(transaction, (TransactionDefinition)definition);
使用事务同步器TransactionSynchronizationManager将当前的事务数据使用ThreadLocal进行绑定。
this.prepareSynchronization(status, (TransactionDefinition)definition);
return status;
} catch (RuntimeException var7) {
this.resume((Object)null, suspendedResources);
throw var7;
} catch (Error var8) {
this.resume((Object)null, suspendedResources);
throw var8;
}
}
}
protected Object doGetTransaction() {
创建一个事务对象
DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
设置事务对象是否允许保存点,保存点是什么自行百度
txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
使用事务同步管理器TransactionSynchronizationManager中获取jdbc的连接信息,为什么此处需要去获取,例如在一个事务中执行多次db的操作,在第一次操作的时候会将获取到的连接使用TransactionSynchronizationManager事务管理同步器进行线程绑定,那么当同一个事务里面,第二次进行db操作那就可以使用之前与线程绑定的连接来复用,因此此处会先获取线程绑定的连接。当然如果是第一次db操作,这里获取到的就是null。那么第一次操作的的时候是如何让获取到数据库连接的呢?在doBegin方法中会有解析
ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.dataSource);
将获取到的数据库连接设置到事务对象中。
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
Connection con = null;
try {
if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
如果当前事务对象是没有数据库连接的,或者数据库连接需要与事务同步,就使用数据源获取数据库连接。
Connection newCon = this.dataSource.getConnection();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
获取数据连接完成后再设置给事务对象
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
给数据库连接设置隔离级别并返回隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
设置隔离级别给事务对象
txObject.setPreviousIsolationLevel(previousIsolationLevel);
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
关闭连接的自动提交,保证多条sql可以在同一个事务一起提交,此处就是jdbc开启事务的核心代码
con.setAutoCommit(false);
}
this.prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);
int timeout = this.determineTimeout(definition);
if (timeout != -1) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
if (txObject.isNewConnectionHolder()) {
通过事务同步管理器将当前连接绑定到当前线程的本地变量
TransactionSynchronizationManager.bindResource(this.getDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable var7) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, this.dataSource);
txObject.setConnectionHolder((ConnectionHolder)null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", var7);
}
}