再次时隔几个月公司的工作,感觉公司的中间件虽然有点粗糙,但是大佬们会去分享设计思路,这个真的很棒,回头再看代码发现以前的事务草稿里面竟然有好长文章,然而我自己都看不懂,删掉之前的重写。
换一个思路去思考这种框架或者中间件的写法,以前是为了面试/纯粹炫技去读,对我本身的提升并没有多少。从我如何去写一个JDBC的事务去看看问题的发展
事务,原生JDBC就带有了事务,本质上Spring就是将其做了一层封装。然后让它尽可能的无感知给我们去快速开发。那么如果没有JDBC,我应该咋办了。现在把基础的代码撸出来
public void transferAccounts(String from,String to,double money) {
//对事务的操作
Connection con = null;
try{
con = JdbcUtils.getConnection();
con.setAutoCommit(false);
//增删该查,干了一堆的活
//提交事务
con.commit();
} catch (Exception e) {
try {
//异常回滚
con.rollback();
} catch (SQLException e1) {
e.printStackTrace();
}
throw new RuntimeException(e);
}
}
这上面就的代码就是开启事务,而不是自动提交,干完活就进行提交,出了错就回滚
注解或者xml bean配置的方式,这里就直接使用注解了,因为不外乎一个解析XML,一个读注解生成的文档
@Transactional(rollbackFor = {SQLException.class})
仅仅默认注解,是不会异常回滚。需要加入rollbackFor,才会回滚。
那么异常的回滚机制,在源码分析里面,我们就只需要看这2个点,看一看spring是怎么将jdbc的代码封装,如果从我的思路来说
1.Connection全局变量,如果是原子模式,用hashmap,保证key的唯一性进行存储,保证每个线程可以取对应的连接
2.切入的方式,就easy了,判断属性,然后选择是否切入。
但是Spring还有几个特点,下图是经典的一张图,我看到了不下数百次?然而还是偶尔会忘其中一个
刚才的代码里面只有回滚规则,spring基于此有事务的其他极大特性,事务超时/是否只读这2个实现都很easy,问题是传播行为,隔离规则,我们需要在代码里面好好看一看。
找到这个解析handler类,
public class TxNamespaceHandler extends NamespaceHandlerSupport {
static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";
static String getTransactionManagerName(Element element) {
return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
}
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
}
因为我之前配置的annotation-driven,所以看这个是写类怎么解析
解析事务的类入口是AnnotationDrivenBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
String mode = element.getAttribute("mode");
if("aspectj".equals(mode)) {
this.registerTransactionAspect(element, parserContext);
} else {
AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
后续就是一段解析。解析的bean结构具体为
1.org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
2.TransactionInterceptor.class
3.BeanFactoryTransactionAttributeSourceAdvisor.class
然后具体逻辑就在代理类里,代理走AOP一套
AOPUTILS里面 APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class)
代理类实在在这里,逻辑是,先查询一次是否有,没有就调用生成。
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if(!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object getCacheKey(Class<?> beanClass, String beanName) {
return beanClass.getName() + "_" + beanName;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if(beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if(Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if(!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if(specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
代理类已经生成,然后找切面。这里都是统一解决完代理类,然后再进行具体的advisor进行织入,逻辑还是基础的。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if(!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
找到相关的adivsor类(因为这里是AbstractAdvisorAutoProxyCreator个类实现类,在AOP的时候是有4个实现的,其实也就是容器化了。),然后进行一一匹配
1.找到容器实现的advisor接口
2.然后进行匹配,判断advisor是不是IntroductionAdvisor,不是就判断是不是PointcutAdvisor
3.其他返回true
debug的时候可以明显的看到PonitCut内容
也就是BeanFactoryTransactionAttributeSourceAdvisor
非静态变量的pointcut,使用的是TransactionAttributeSourcePointcut
主要是使用match方法,match方法又是封装在AOPUTILS.canApply来解决。
然后在动态代理里面,其实就是
遍历所有使用的 Advisor,获得其Advice,将Advice转为MethodInterceptor。
在事务里面也就是开始几个基础bean容器中的TransactionInterceptor类
具体的事务逻辑就在transactionAspectSupport
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
//获取事务配置
final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
//事务管理器判断是否开启
final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
//切入点名定义
final String joinpointIdentification = this.methodIdentification(method, targetClass);
if(txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
//.....
} else {
//开启事务
TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
retVal = invocation.proceedWithInvocation();
} catch (Throwable var15) {
this.completeTransactionAfterThrowing(txInfo, var15);
throw var15;
} finally {
this.cleanupTransactionInfo(txInfo);
}
this.commitTransactionAfterReturning(txInfo);
return retVal;
}
}
protected TransactionAspectSupport.TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
TransactionStatus status = null;
if(txAttr != null) {
if(tm != null) {
//获得事务
status = tm.getTransaction((TransactionDefinition)txAttr);
} else if(this.logger.isDebugEnabled()) {
this.logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured");
}
}
return this.prepareTransactionInfo(tm, (TransactionAttribute)txAttr, joinpointIdentification, status);
}
最下面的获取代码如下,是一个threadlocal来判断当前线程事务的获取
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal("Transactional resources");
private static Object doGetResource(Object actualKey) {
Map<Object, Object> map = (Map)resources.get();
if(map == null) {
return null;
} else {
Object value = map.get(actualKey);
if(value instanceof ResourceHolder && ((ResourceHolder)value).isVoid()) {
map.remove(actualKey);
if(map.isEmpty()) {
resources.remove();
}
value = null;
}
return value;
}
}
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
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) {
throw new InvalidTimeoutException("Invalid transaction timeout", ((TransactionDefinition)definition).getTimeout());
} else if(((TransactionDefinition)definition).getPropagationBehavior() == 2) {
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) {
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);
}
try {
boolean newSynchronization = this.getTransactionSynchronization() != 2;
DefaultTransactionStatus status = this.newTransactionStatus((TransactionDefinition)definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
this.doBegin(transaction, (TransactionDefinition)definition);
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;
}
}
}
PROPAGATION_NOT_SUPPORTED 事务逻辑可以看到
if(definition.getPropagationBehavior() == 4) {
if(debugEnabled) {
this.logger.debug("Suspending current transaction");
}
//在这里将事务从原本线程进行移除,然后进行再新建
suspendedResources = this.suspend(transaction);
newSynchronization = this.getTransactionSynchronization() == 0;
return this.prepareTransactionStatus(definition, (Object)null, false, newSynchronization, debugEnabled, suspendedResources);
}else if(definition.getPropagationBehavior() == 3) {
//..
DefaultTransactionStatus status = this.newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
this.doBegin(transaction, definition);
this.prepareSynchronization(status, definition).
//..
}
整个事务创建的使用是DataSourceTransactionManager
doBegin来创建
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
Connection con = null;
try {
if(txObject.getConnectionHolder() == null || 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");
}
con.setAutoCommit(false);
}
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);
}
}
其他的方法也是最终调用的该类的其他方法