@Transactional 简单使用
事务提交回滚操作其实和业务并没有太大关系,如果每次写业务逻辑都需要去写这样一大坨逻辑,还是比较烦的,所以 Spring 就提供 @Transactional 注解来帮我们实现这些和业务不相关代码。而开发只需关注开发业务。下面简单演示下 @Transactional 注解的使用。
定义 Person 类,在方法 show() 加上 @Transactional 修饰,代码如下:
@Component
public class Person {
@Transactional
public void show(String name) {
System.out.println("======>数据库操作...");
}
}
在使用 @Transactional 注解时,一定要记住把 @EnableTransactionManagement 注解加上,否则事务不生效。具体为什么在源码分析就会知道。
@ComponentScan
@EnableTransactionManagement
public class AopProxyTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopProxyTest.class);
Person bean = context.getBean(Person.class);
bean.show("abc");
}
}
源码分析
@Import 导入配置类
接着上提到的为什么要加上 @EnableTransactionManagement 注解,其实是因为这个注解里面通过 @Import 注解导入支持事务功能的类,源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
AdviceMode mode() default AdviceMode.PROXY;
}
默认使用 AdviceMode.PROXY 模式,进入 TransactionManagementConfigurationSelector 类,源码如下:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
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;
}
}
}
可以看到引入两个类 AutoProxyRegistrar、ProxyTransactionManagementConfiguration。AutoProxyRegistrar 类必然实现 ImportBeanDefinitionRegistrar 接口,实现这个接口就可以被 Spring 扫描,然后去实例化该接口导入的类。进入 AutoProxyRegistrar 源码如下:
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
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;
}
}
}
}
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 缓存和事物都是通过这个 InfrastructureAdvisorAutoProxyCreator 基础增强类来生成代理对象
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
}
该类在 registerBeanDefinitions() 方法中导入了 InfrastructureAdvisorAutoProxyCreator 类,观察这个类的特点实现了 AbstractAutoProxyCreator 自动创建代理类抽象类,并且实现了 BeanPostProcessor 接口。所以只需要关注这两个类各自的方法即可。
首先看到 BeanPostProcessor#postProcessBeforeInitialization() 方法,源码如下:
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
很显然 InfrastructureAdvisorAutoProxyCreator 类在该方法中并没有做任何操作,略过。
继续看到 BeanPostProcessor#postProcessAfterInitialization() 方法,源码如下:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
/** 获取缓存 key */
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
/** 找到合适的就会被代理 */
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
AbstractAutoProxyCreator 代理模版抽象类(传统 AOP 实现类)
但是这段逻辑是一个模版模式,也就是一段公共逻辑,所以是在 AbstractAutoProxyCreator 抽象类中写的。因为 AbstractAutoProxyCreator 类是一个抽象类,不可能被实例化的,那么如何会调用到这段逻辑呢?肯定需要去找这个抽象类的子类,所以 InfrastructureAdvisorAutoProxyCreator 类就去实现 AbstractAutoProxyCreator 类。所以可以看出 @EnableTransactionManagement
注解只是引入一个入口类,在这里入口类中并没有做什么逻辑,有用逻辑都是在它父类 AbstractAutoProxyCreator 中完成。
进入 wrapIfNecessary() 方法,核心源码如下:
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));
return proxy;
}
return bean;
}
getAdvicesAndAdvisorsForBean()
方法会去收集当前 bean 有哪些 Advisor 可以对其增强。如果找到有 Advisor 可以对其增强,就会调用 createProxy()
方法为其创建代理对象。比如 Person bean 肯定是有 Advisor 的。为什么?因为 Person#show() 方法上有 @Transactional 注解修饰。Spring 会去扫描并解析此注解,然后创建 Advisor 增强器进行相应处理。而这个 Advisor 增强逻辑就是:自动开启、提交、回滚事务。
现在已经通过 InfrastructureAdvisorAutoProxyCreator 类最终调用到 getAdvicesAndAdvisorsForBean()
方法找 Advisor,找到 Advisor 就会给 Person 创建代理对象。所以从这里就可以认为 InfrastructureAdvisorAutoProxyCreator 类其实就是触发类,也可说是个入口引导类,没有这入口就不会触发去创建代理对象。所以这 @EnableTransactionManagement
注解一定记得加上。
Advisor 切面增强类
那么现在就要关注下这个 Advisor 在哪里创建的?
在最前面 @EnableTransactionManagement 注解其实引入了两个类,一个是 AutoProxyRegistrar 类,另一个是 ProxyTransactionManagementConfiguration 类,AutoProxyRegistrar 类已经讲完,所以这里就去看看第二个类,核心源码如下:
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
/**
* 配置一个 Advisor,Advisor = Advice + Pointcut
*/
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
/**
* 配置一个 Advice 实际增强逻辑
*/
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
/**
* 这个类就是去解析 @Transactional 注解属性然后封装成 TransactionAttribute 对象
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
很显然在这里通过 Configuration + @Bean 配置类方式注入 BeanFactoryTransactionAttributeSourceAdvisor 增强类。而我们知道 Advisor = Advice + Pointcut 这两部分组成,Advice 也是通过 @Bean 注解完成的,就是上面代码中的 TransactionInterceptor 类,所有切面增强逻辑(开启事务、提交、回滚等操作)都会在该 Advice 中。然后再看到 Pointcut = ClassFilter + MethodMatcher 两部分组成,
进入 TransactionAttributeSourcePointcut 类,源码如下:
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
// tc_tag3: 此处开始通过 AbstractFallbackTransactionAttributeSource 解析事务属性 返回上一层 tc_tag2
// 只要这个 method 方法上面能够拿到 TransactionAttribute 事物属性就返回 true ,然后会去生成代理对象
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
}
从源码中可以看出在 TransactionAttributeSourcePointcut 类构造方法中设置 ClassFilter,进入 TransactionAttributeSourceClassFilter 类,核心源码如下:
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
继续进入 isCandidateClass() 方法,源码如下:
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
if (annotationName.startsWith("java.")) {
return true;
}
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}
从源码中可以看到前两个 if 条件根本不会走,一直返回 true,所以从这里就可以知道 TransactionAttributeSourceClassFilter 类的过滤条件,对类根本不做任何判断,也就是说这个类其实是个摆设。但是仔细想想,如果不对类进行判断,那我们标注再类上的 @Transactional 就不去生成代理对象么?
答案是也会去生成代理对象的。其实这个过滤,在 ClassFilter 中没有做处理,但是在 MethodMatcher 中有处理,也就是说在 MethodMatcher 中既做了对类的扫描,也做了对方法的扫描,合二为一。所以上述的 ClassFilter 就成了一个摆设。看到 MethodMatcher 的实现类 TransactionAttributeSourcePointcut,核心源码如下:
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
// tc_tag3: 此处开始通过 AbstractFallbackTransactionAttributeSource 解析事务属性 返回上一层 tc_tag2
// 只要这个 method 方法上面能够拿到 TransactionAttribute 事物属性就返回 true ,然后会去生成代理对象
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
}
看到 matches() 匹配方法中 getTransactionAttribute() 方法,就是去判断类上或者方法上是否有 @Transactional 注解修饰,如果有就会去生成代理对象。核心源码如下:
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// tc_tag5: 查询缓存判断该方法是否已经解析过了
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
}
else {
// tc_tag6: 去计算事务的属性
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// tc_tag12: 将解析好了的事务属性添加到缓存,下次就不用再次计算了
this.attributeCache.put(cacheKey, txAttr);
return txAttr;
}
}
从上面源码可以看到如果解析到有 @Transactional 注解,会包装成 TransactionAttribute 对象,然后放入到缓存中,后面只需要从缓存中拿值。然后在看到 computeTransactionAttribute()
方法是如何去解析 @Transactional 注解,核心源码如下:
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// tc_tag6: 必须是 public 修饰的方法
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// tc_tag7: 获取该接口实现类具体方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// tc_tag8: 尝试从实现类方法上找是否标注了 @Transactional 注解,然后将解析的值封装成 TransactionAttribute 对象,找到了直接返回
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// tc_tag9: 尝试从实现类类上面找是否标注了 @Transactional 注解,然后将解析的值封装成 TransactionAttribute 对象,找到了直接返回
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// tc_tag10: 尝试从接口方法中找是否标注了 @Transactional 注解,然后将解析的值封装成 TransactionAttribute 对象,找到了直接返回
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// tc_tag11: 尝试从接口类上面找是否标注了 @Transactional 注解,然后将解析的值封装成 TransactionAttribute 对象,找到了直接返回
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
从上面的源码中可以看出,@Transactional 注解修饰的方法必须是 public 修饰,然后再判断方法上是否有注解@Transactional ,方法上没找到就找类上,类上找不到,就去接口中的方法中找,还找不到就去找接口上是否有 @Transactional 注解,都没有那就返回 null,说明当前 bean 不需要创建代理对象。
进入 findTransactionAttribute() 方法,就是去类或者方法上找是否有 @Transactional 注解,核心源码如下:
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
分析到这里,应该清楚 Pointcut 中的 MethodMatcher 方法匹配逻辑。而 ClassFilter 这里是不需要关注的。
okay,现在继续回到 wrapIfNecessary()
方法,核心源码如下:
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));
return proxy;
}
return bean;
}
前面说过 getAdvicesAndAdvisorsForBean()
方法回去给当前 bean 找到有没有 Advisor,如果有就会创建代理对象,现在进入这个方法看下是怎么匹配过程。核心源码如下:
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
/** tc_tag-99: 查找适合这个类的 advisors 切面通知 */
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
进入 findEligibleAdvisors()
方法,核心源码如下:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
return eligibleAdvisors;
}
从上面源码可以看出 findCandidateAdvisors() 方法会收集到所有的 Advisor,findAdvisorsThatCanApply() 方法会去匹配有哪些 Advisor 能够适合当前的 bean。这个匹配其实是调用上面说的ClassFilter、 MethodMatcher 匹配器,这两个匹配的过程上面已经说过,这里不过多重复。
进入 findCandidateAdvisors() 方法,核心源码如下:
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
return advisors;
}
先看到这一段逻辑,如下:
if (advisorNames == null) {
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
通过 Spring 提供的 BeanFactoryUtils 工具类,获取到工程下所有实现了 Advisor 接口类,在前面通过 @EnableTransactionManagement 注解导入配置类 ProxyTransactionManagementConfiguration 中就通过 @Bean 注解注入 BeanFactoryTransactionAttributeSourceAdvisor ,所以这里就能够获取到该类。
然后再看到这段逻辑,如下:
for (String name : advisorNames) {
if (isEligibleBean(name)) {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
将找到的 Advisor 添加到集合 advisors 中。现在 advisors 集合中肯定有 BeanFactoryTransactionAttributeSourceAdvisor 类,因为这个类实现了 Advisor 接口。
回到上一层调用处,findEligibleAdvisors() 方法已经拿到所有的 Advisor 的增强器。那么接下来就是要去匹配有哪些增强器能够用于当前 bean。
```java
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
return eligibleAdvisors;
}
继续看到 findAdvisorsThatCanApply()
方法,这其实就是调用 ClassFilter、MethodMatcher 对象匹配过程,核心源码如下:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
for (Advisor candidate : candidateAdvisors) {
// tc_tag-96: 开始 for 循环 candidateAdvisors 每个增强器,看是否能使用与这个 bean
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
遍历 candidateAdvisors 增强器,挨个匹配是否能够用于当前 bean。进入 canApply() 方法,核心源码如下:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
/**
* tc_tag2: 注意对于 @Transactional 注解的 Pointcut 匹配还是比较复杂的,匹配逻辑在 TransactionAttributeSourcePointcut
*/
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
上面整段代码的逻辑就是拿到之前创建好的 ClassFilter、MethodMatcher 对象,然后去看这个类,假设是 Person 类上是否有 @Transactional,遍历 Person 类中每个方法上是否有 @Transactional 注解修饰。只要发现有 @Transactional 注解就认为 Advisor 适用于这个类,那么后面就会给这个类创建代理对象。
继续回到上一层调用处 wrapIfNecessary() 方法,核心源码如下:
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));
return proxy;
}
return bean;
}
getAdvicesAndAdvisorsForBean()
方法已经找到当前 bean 有哪些 Advisor,接下来就是调用 createProxy()
方法创建代理对象,这里是类的代理,所有采用 cglib 代理方式。cglib 调用过程不过多讲述,和 jdk 基本无差别。
TransactionInterceptor 切面增强逻辑
上面代理对象已经创建成功,并且切面增强类也包装到代理对象中。现在继续关注 @Transactional 切面是怎么处理的,看它如何开启事务、提交、回滚。进入切面增强类 BeanFactoryTransactionAttributeSourceAdvisor,然后关注他的 Advice 类 TransactionInterceptor,核心源码如下:
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// tc_tag16: 开始要去调用事务方法了
return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
@Override
@Nullable
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
@Override
public Object getTarget() {
return invocation.getThis();
}
@Override
public Object[] getArguments() {
return invocation.getArguments();
}
});
}
进入 invokeWithinTransaction() 方法,核心源码如下:
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// tc_tag: 开始调用目标方法,如果目标方法中又有代理方法的话,就会重新过来执行代理逻辑
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// tc_tag24: 执行目标方法报错了,开始回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
// tc_tag: 存储被挂起的事务(也就是第一个获取得 Connection 连接)
// 底层代码: transactionInfoHolder.set(this.oldTransactionInfo);
cleanupTransactionInfo(txInfo);
}
// tc_tag25: 最后提交事物
commitTransactionAfterReturning(txInfo);
return retVal;
}
}
在上述源码中 createTransactionIfNecessary() 方法会去开启事务、invocation.proceedWithInvocation() 执行目标方法,completeTransactionAfterThrowing() 回滚事务、commitTransactionAfterReturning() 提交事务。现在逐一分析下这几个方法,首先看到 createTransactionIfNecessary() 方法,核心源码如下:
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
status = tm.getTransaction(txAttr);
}
}
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// 省略...
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
// tc_tag: 获取数据源,设置自动提交为 false,绑定数据源(存在 ThreadLocal)
doBegin(transaction, definition);
return status;
}
进入 doBegin() 方法,核心源码如下:
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// tc_tag: 从数据源中获取连接
Connection newCon = obtainDataSource().getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
// tc_tag23_8: 设置 autoCommit 自动提交为 false
con.setAutoCommit(false);
}
txObject.getConnectionHolder().setTransactionActive(true);
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
}
}
在这里开启事务,从数据库连接池中获取到一个 Connection 代理对象,然后设置自动提交,超时时间等等。然后继续看到 commitTransactionAfterReturning() 提交方法,核心源码如下:
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
@Override
public final void commit(TransactionStatus status) throws TransactionException {
// 省略...
processCommit(defStatus);
}
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
// 省略...
doCommit(status);
// 省略...
}
@Override
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on Connection [" + con + "]");
}
try {
con.commit();
}
catch (SQLException ex) {
throw translateException("JDBC commit", ex);
}
}
从 doCommit() 方法中就可以看出拿到上面创建好的数据库池对象,然后进行 commit() 提交。最后在看看回滚的操作,进入 completeTransactionAfterThrowing() 方法,核心源码如下:
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
// 省略...
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
// 省略...
}
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 调用自己的方法
processRollback(defStatus, false);
}
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
// 省略...
doRollback(status);
// 省略...
}
继续进入 doRollback() 方法,核心源码如下:
@Override
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
}
try {
con.rollback();
}
catch (SQLException ex) {
throw translateException("JDBC rollback", ex);
}
}
从源码可以看到还是获取之前创建的数据库连接池代理对象,然后调用 rollback() 方法进行回滚。在调用的过程中有很多细节地方需要注意,这里不过多展开。以上就是对 @Transactional 注解作用简单分析。