spring事务是在spring aop切面代理以及spring jdbc的基础上构建的。因此在了解事务的实现原理之前必须对这3个架构有一定的了解
要开启Spring事务需要添加注解@EnableTransactionManagement
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//是否直接代理目标class(即通过cglib代理),默认先通过接口代理。
boolean proxyTargetClass() default false;
//代理模式PROXY(JDK) ,ASPECTJ
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
通过注解的属性名称可以猜测属性的作用,具体逻辑在后续的代码实现中进行分析。通过这个注解可以看到是@Import(TransactionManagementConfigurationSelector.class)了一个类,因此直接看这个类。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
}
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {
@Override
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
//获取类上泛型类型(即EnableTransactionManagement)
Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
//从当前正在注入的bean中的所有注解中获取EnableTransactionManagement注解的属性
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (attributes == null) {
throw new IllegalArgumentException(String.format(
"@%s is not present on importing class '%s' as expected",
annType.getSimpleName(), importingClassMetadata.getClassName()));
}
//从EnableTransactionManagement注解的属性获取mode属性值
AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
//由子类实现
String[] imports = selectImports(adviceMode);
if (imports == null) {
throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
}
return imports;
}
}
其实这里逻辑很简单,获取class上EnableTransactionManagement的注解AdviceMode属性,根据不同的配置去注入不同的bean实现。
(至于import实现是怎么实现的,逻辑在ConfigurationClassPostProcessor中,这里不做展开,属于spring容器的基础内容,在这里只要知道spring通过selectImports方法将返回的bean注入到spring容器中)
//省略不重要代码
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
public abstract class AopConfigUtils {
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
}
其核心逻辑就是当容器中不存在org.springframework.aop.config.internalAutoProxyCreator的时候默认注入InfrastructureAdvisorAutoProxyCreator的bean。从这里可以看出spring事务是必须要有aop的支持。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return bean;
}
}
可以看出这里的逻辑是通过getAdvicesAndAdvisorsForBean方法获取到切面和切点,来判断是否需要创建代理。
这个方法的逻辑是从spring容器中获取Advisor,并且通过AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)去决定是否需要
代理。其核心逻辑是Pointcut接口中获取MethodMatcher,并通过matcher接口方法来最终实现。而事务的advisor是BeanFactoryTransactionAttributeSourceAdvisor,
因此其matcher实现逻辑就在其中。后续分析
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
}
在这个Configuration中注入了BeanFactoryTransactionAttributeSourceAdvisor,通过继承关系可以发现其实就是Advisor。
在之前的AbstractAutoProxyCreator以来查找的Advisor就是这里注入的。
通过源码可以发现Spring的Advisor其实是组合了Pointcut和Advice而他们的具体实现分别是AnnotationTransactionAttributeSource和TransactionInterceptor。
其实到了这里AOP的基本组件都已经齐全了。之后具体看下Spring事务advice的具体是如何实现事务语意的。
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
}
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
//获取注解属性
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//获取TransactionManager,不设置的情况下默认取容器PlatformTransactionManager
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//此处源码比较复杂,数据库事务具体实现在spring-jdbc中不做展开,大致逻辑是初始化一个TransactionInfo里面初始化了事务的状态等信息
//DataSourceTransactionManager会将connection的autocommit设置为false。
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
//执行被代理对象方法逻辑
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
//根据异常判断是回滚还是提交
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清除TransactionInfo
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
}
}
以上代码除了创建部分逻辑有些复杂,其他部分都是很好理解的。这里为止spring事务原理分析就结束了,当然其中还有许多细节还未分析。
spring事务借助了spring容器,spring-aop模块以及TransactionManager的实现类帮助开发者只需要通过Trancastion注解即可自动在方法前开启事务,
在异常回滚事务,方法结束执行事务。不需要开发者手动的编写这些重复的事务代码,提升开发效率。通过了解他的实现原理也能规避一些使用上的错误,从而导致事务的失效等问题。
后续也许会为spring-aop单独在写一篇吧