前言
猿猿們都知道,IOC和AOP很重要,事務也很重要,事務其實和AOP差不多,技術和代碼有很多相似之處,爲防止沒有看AOP源碼解析的看官,這篇解析事務源碼的博文,不會因爲跟AOP代碼重複就跳過解析。
類結構體系
示例代碼
配置類
@Configurable
@ComponentScan(value = "com.ambition")
@EnableTransactionManagement
@EnableAspectJAutoProxy(exposeProxy = true)
public class TransactionConfig {
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
接口和實現類
public interface PayService {
void pay();
void deduction();
}
@Service
public class PayServiceImpl implements PayService {
@Transactional(rollbackFor = Exception.class)
@Override
public void pay() {
System.out.println("準備支付");
((PayService) AopContext.currentProxy()).deduction();
System.out.println(1 / 0);
System.out.println("支付完成");
}
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
@Override
public void deduction() {
System.out.println("準備扣減");
System.out.println(1 / 0);
System.out.println("扣減完成");
}
}
測試類
public class TransactionTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(TransactionConfig.class);
context.refresh();
PayService pay = context.getBean(PayService.class);
pay.pay();
}
}
產生過程
老規矩,先來看一下Spring IOC容器是怎麼對它進行初始化的,再看它的創建過程,最後看執行過程。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
// 指示是否要創建基於子類的(CGLIB)代理,而不是標準的基於 Java 接口的代理
boolean proxyTargetClass() default false;
// 指出如何應用事務通知
AdviceMode mode() default AdviceMode.PROXY;
// 當在特定的連接點上應用多個通知時,指示事務增強器的執行順序
int order() default Ordered.LOWEST_PRECEDENCE;
}
可以看到這個註解上面還有一個@Import註解,導入了一個TransactionManagementConfigurationSelector類,它是ImportSelector類型,解析IOC源碼的時候,可以看到Spring會調用它的selectImports()
方法,獲取類的全限定名數組,然後進行遞歸解析。
public class TransactionManagementConfigurationSelector
extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
// 默認是基於 JDK 代理的通知
case PROXY:
return new String[]{AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
// 基於 AspectJ 編織的通知
case ASPECTJ:
return new String[]{determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
可以看到這個方法會註冊兩個BeanDefinition,一個是AutoProxyRegistrar,類型是ImportBeanDefinitionRegistrar,另一個是ProxyTransactionManagementConfiguration,它是一個加了@Configuration註解的配置類。
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**
* beanName 爲 org.springframework.transaction.config.internalTransactionAdvisor
*
* @see BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans()
**/
@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;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@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;
}
}
這個配置類又會往容器中註冊BeanFactoryTransactionAttributeSourceAdvisor,AnnotationTransactionAttributeSource和TransactionInterceptor三個類。
看一下各個組件的注入:
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) {
// 獲取註解
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
// 解析 mode 註解值
Object mode = candidate.get("mode");
// 解析 proxyTargetClass 註解值
Object proxyTargetClass = candidate.get("proxyTargetClass");
// 校驗
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass()
&& Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
// 基於 JDK 代理的通知,不指定則默認
if (mode == AdviceMode.PROXY) {
// 註冊 InfrastructureAdvisorAutoProxyCreator 組件
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
// 默認是 False
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
......
}
}
這個類又往IOC容器中註冊了一個InfrastructureAdvisorAutoProxyCreator類。看類結構圖,發現跟AOP很相似,也會利用Spring的回調進行必要組件的初始化,利用後置處理器的調用進行一些邏輯處理。
需要的組件都註冊到IOC容器中了,只需要藉助IOC容器的初始化過程進行初始化就行了。
總結一下就是:IOC容器初始化時會去找事務相關的信息,先做緩存和創建增強器的操作,初始化目標類的時候再將可用的增強器織入到目標類中生成代理對象。
代碼從AbstractAutowireCapableBeanFactory的createBean()
方法開始:
protected Object createBean(String beanName,
RootBeanDefinition mbd,
@Nullable Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
......
try {
/**
* 給 BeanPostProcessors 一個返回代理而不是目標 Bean 實例的機會【重要】
* 但此時還沒有創建代理對象,此時沒有對象,只有 BeanDefinition
*
* 第一次調用後置處理器【跟 AOP 有關】
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization(java.lang.Object, java.lang.String)
*
* InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
* Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
*
* 此時對象還沒有實例化,只有 BeanDefinition
* 無法進行代理,只是將切面找出來進行緩存
*/
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException();
}
try {
/**
* 實例化 Bean
**/
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
......
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException();
}
}
還是resolveBeforeInstantiation()
這個方法,將事務相關的信息進行緩存,這個方法進去調用的是InstantiationAwareBeanPostProcessor類型的postProcessBeforeInstantiation()
方法,如果返回值爲空,就不會調用applyBeanPostProcessorsAfterInitialization()
方法了。
從上面的類結構圖中可以看到,AbstractAutoProxyCreator是InstantiationAwareBeanPostProcessor類型,所以會進到它的postProcessBeforeInstantiation()
方法:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 生成緩存建
Object cacheKey = getCacheKey(beanClass, beanName);
// beanName 爲空 或者 目標源緩存中不存在
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
/**
* 是基礎結構類 或者 beanName 表示"原始實例"
*
* 【Advice,Pointcut,Advisor 和 AopInfrastructureBeans 視爲基礎結構類】
* 【beanName 以 beanClass 名稱開頭,以 ".ORIGINAL" 結尾代表"原始實例"】
**/
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
/**
* 如果有自定義的 TargetSource,在此處創建代理
* 抑制目標 Bean 的不必要的默認實例化:TargetSource 將以自定義方式處理目標實例
*
* 如果沒有爲 AbstractAutoProxyCreator 注入 TargetSourceCreator,則結果都爲 null
* @see AbstractAutoProxyCreator#setCustomTargetSourceCreators(org.springframework.aop.framework.autoproxy.TargetSourceCreator...)
**/
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
// 存入目標源緩存
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 獲取所有合格的增強器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 創建 AOP 代理
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
// 存入緩存
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
然後看一下AbstractAutowireCapableBeanFactory的initializeBean()
方法,在調用applyBeanPostProcessorsAfterInitialization()
方法進行包裝的時候,調用了BeanPostProcessor類型的後置處理器的postProcessAfterInitialization()
方法,這裏就會進到AbstractAutoProxyCreator的postProcessAfterInitialization()
方法:
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) {
// beanName不爲空 並且 存在於目標源緩存中【後者一般不滿足】
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 存在緩存中 且 沒有代理過
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/**
* 是基礎結構類 或者 beanName 表示"原始實例"
*
* 【Advice,Pointcut,Advisor 和 AopInfrastructureBeans 視爲基礎結構類】
* 【beanName 以 beanClass 名稱開頭,以 ".ORIGINAL" 結尾代表"原始實例"】
**/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
/**
* 獲取所有合格的增強器
*
* 通過註解方式和 XML【<aop:advisor>】 方式配置的增強器
**/
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;
}
// 否則標記爲未代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
getAdvicesAndAdvisorsForBean()
方法就是緩存和獲取的過程:
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass,
String beanName,
@Nullable TargetSource targetSource) {
// 獲取所有合格的增強器
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
// 沒找到則認爲不需要代理
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 獲取所有候選增強器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 查找可以應用於指定 bean 的所有增強器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 擴展增強器【空方法】
extendAdvisors(eligibleAdvisors);
// 有則排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
這裏的findAdvisorsThatCanApply()
方法包含了查找可以應用的增強器的過程,這個後面再說,先看findCandidateAdvisors()
方法
protected List<Advisor> findCandidateAdvisors() {
// 用回調時生成的 BeanFactoryAdvisorRetrievalHelperAdapter 組件進行查找
return this.advisorRetrievalHelper.findAdvisorBeans();
}
這裏就使用到了IOC容器回調AbstractAdvisorAutoProxyCreator時實例化的BeanFactoryAdvisorRetrievalHelperAdapter組件進行查找操作:
public List<Advisor> findAdvisorBeans() {
/**
* 確定通知器程序 beanName 列表(如果尚未緩存)
**/
String[] advisorNames = this.cachedAdvisorBeanNames;
// 沒有則解析
if (advisorNames == null) {
/**
* 從容器中獲取所有實現 Advisor 的 beanName
*
* 這裏會有一個 org.springframework.transaction.config.internalTransactionAdvisor
* 類爲 BeanFactoryTransactionAttributeSourceAdvisor
**/
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 存入緩存
this.cachedAdvisorBeanNames = advisorNames;
}
// 沒找到直接返回空集合
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
// 遍歷找到的通知器
for (String name : advisorNames) {
// beanName 是合格的通知
if (isEligibleBean(name)) {
/**
* 下面調用 this.beanFactory.getBean(name, Advisor.class) 方法時,會將 name 標記爲當前正在創建
* 之後除非創建完成,否則不會走 else 分支
**/
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
/**
* 創建 Advisor 實例
*
* 這裏會創建 BeanFactoryTransactionAttributeSourceAdvisor
**/
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
找到候選的增強器之後,再去篩選可以用的,看一下findAdvisorsThatCanApply()
方法,最後調用的是AopUtils的findAdvisorsThatCanApply()
方法:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors,
Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 先找 IntroductionAdvisor 類型的可用增強器
for (Advisor candidate : candidateAdvisors) {
/**
* 是 IntroductionAdvisor 類型 且 可以應用於目標方法
*
* BeanFactoryTransactionAttributeSourceAdvisor 不是 IntroductionAdvisor 類型
**/
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
// 有合格的增強器
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 從候選的增強器中查找適用的
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
因爲BeanFactoryTransactionAttributeSourceAdvisor不是 IntroductionAdvisor類型,所以會調用第二個canApply()
方法:
public static boolean canApply(Advisor advisor,
Class<?> targetClass,
boolean hasIntroductions) {
// 先處理 IntroductionAdvisor 類型
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
/**
* 再處理 PointcutAdvisor 類型
*
* 之前創建的 InstantiationModelAwarePointcutAdvisor 是 PointcutAdvisor 的子類
* 之前創建的 BeanFactoryTransactionAttributeSourceAdvisor 是 PointcutAdvisor 的子類
**/
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
/**
* 沒有切入點,因此假設它適用
**/
return true;
}
}
又封裝了一層,再進到canApply()
方法:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
// 過濾器不匹配
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// 方法匹配器,這裏是 BeanFactoryTransactionAttributeSourceAdvisor
MethodMatcher methodMatcher = pc.getMethodMatcher();
// 是 TrueMethodMatcher 則直接返回適用
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
// 是 IntroductionAwareMethodMatcher 類型,這裏不是
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) {
// 獲取類定義的方法,包括父類 Object 的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
/**
* 是否匹配
*
* introductionAwareMethodMatcher 爲空,調用的是 TransactionAttributeSourcePointcut 的 matches() 方法
* @see org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches(java.lang.reflect.Method, java.lang.Class)
**/
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
這裏主要是想帶大家看一下解析事務註解的代碼,過程很曲折坎坷,但是也要耐下心來先看TransactionAttributeSourcePointcut的matches()
方法:
public boolean matches(Method method, Class<?> targetClass) {
// 獲取 AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
/**
* 調用的是父類 AbstractFallbackTransactionAttributeSource 的方法
* @see AbstractFallbackTransactionAttributeSource#getTransactionAttribute(java.lang.reflect.Method, java.lang.Class)
**/
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
再跟到AbstractFallbackTransactionAttributeSource的getTransactionAttribute()
方法:
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Object 類的方法直接返回空
if (method.getDeclaringClass() == Object.class) {
return null;
}
Object cacheKey = getCacheKey(method, targetClass);
// 嘗試從緩存中獲取
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
/**
* 值可以是表示沒有事務屬性的規範值,也可以是實際事務屬性
*
* 如果是默認值【DefaultTransactionAttribute】則返回空
**/
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
// 緩存中沒有,則進行解析
else {
// 獲取 @Transactional 註解的屬性
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// 空對象則向緩存中加入一個默認值【DefaultTransactionAttribute】
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
// 獲取實際的方法名
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
/**
* 爲事務屬性設置一個方法描述符,以後遇到這個方法則可以直接使用
* 僅限於 TransactionAttribute 是 DefaultTransactionAttribute 類型
*
* @see TransactionAspectSupport#methodIdentification(java.lang.reflect.Method, java.lang.Class, org.springframework.transaction.interceptor.TransactionAttribute)
**/
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
// 加入緩存
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
終於要到了,看一下computeTransactionAttribute()
方法:
protected TransactionAttribute computeTransactionAttribute(Method method,
@Nullable Class<?> targetClass) {
/**
* 不允許使用非公開方法
**/
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
/**
* 該方法可能在接口上,但是需要目標類的屬性
* 如果目標類爲空,則該方法將保持不變
**/
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
/**
* 獲取 @Transactional 註解的屬性
*
* 先從目標方法上獲取
* 再從目標方法的類上獲取
* 再從目標類實現的接口方法上獲取
* 再從目標類實現的接口方法的類上獲取
**/
/**
* 首先嚐試的是目標類中的方法
**/
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
/**
* 再嘗試目標類上的 @Transactional 屬性
**/
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
/**
* 後備是看原始方法
**/
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
/**
* 最後一個後備是原始方法的類
**/
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
這裏的代碼就解釋了,爲什麼@Transactional註解加在實現類的方法上、實現類上、接口的方法上和接口類上都能起到事務的作用,因爲這裏會按順序去查找,查找的findTransactionAttribute()
很重要,最後調用的是SpringTransactionAnnotationParser的parseTransactionAnnotation()
方法:
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 獲取合併的註解屬性
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element,
Transactional.class,
false,
false
);
// 解析事務註解
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
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;
}
這些屬性是不是很熟悉呢,這就是我想帶大家看的。之後IOC容器創建目標類的時候,就會把事務通知器織入到目標類中,創建代理對象。
創建過程
創建工作還是從AbstractAutowireCapableBeanFactory的initializeBean()
開始,當解析帶有事務註解的類時,就會將事務增強器織入到目標類,創建一個代理對象。
protected Object initializeBean(final String beanName,
final Object bean,
@Nullable RootBeanDefinition mbd) {
// 回調 Aware 及其實現類的方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
},
getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
/**
* 關鍵字:執行
* 執行 BeanPostProcessor 直接實現類的 postProcessBeforeInitialization() 方法
*
* @PostConstruct 註解是在這裏面進行處理的
*/
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
/**
* 執行 Bean 生命週期回調中的 init 方法
*
* 實現 InitializingBean 接口並重寫 afterPropertiesSet() 方法是在這裏面進行處理的
*/
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException();
}
if (mbd == null || !mbd.isSynthetic()) {
/**
* 關鍵字:改變
* 執行 BeanPostProcessor 直接實現類的 postProcessAfterInitialization() 方法
*
* 產生 AOP 代理,事務的代理等
*/
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
applyBeanPostProcessorsAfterInitialization()
方法跟進去,發現其調用了BeanPostProcessor類型的後置處理器的postProcessAfterInitialization()
方法,這裏就會進到AbstractAutoProxyCreatorpostProcessAfterInitialization()
方法。
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;
}
代碼上面已經看過,只是上面主要是緩存和創建事務增強器的過程,這裏是創建目標代理對象的過程。因爲IOC容器創建每個Bean都會經歷這個過程,會重複調用後置處理器,所以貼代碼不能很好的區分。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// beanName不爲空 並且 存在於目標源緩存中【後者一般不滿足】
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 存在緩存中 且 沒有代理過
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/**
* 是基礎結構類 或者 beanName 表示"原始實例"
*
* 【Advice,Pointcut,Advisor 和 AopInfrastructureBeans 視爲基礎結構類】
* 【beanName 以 beanClass 名稱開頭,以 ".ORIGINAL" 結尾代表"原始實例"】
**/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
/**
* 獲取所有合格的增強器
*
* 通過註解方式和 XML【<aop:advisor>】 方式配置的增強器
**/
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;
}
// 否則標記爲未代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
這裏執行完,就可以看到目標類被織入了事務增強器,變成了一個代理對象。
執行過程
現在我們有了一個帶有事務增強器的代理對象,可以調用它的事務方法了,會進到JdkDynamicAopProxyinvoke()
方法中:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 代理接口沒有定義 equals 方法 且 調用的是目標對象的 equals 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
// 代理接口沒有定義 hashCode 方法 且 調用的是目標對象的 hashCode 方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
// 聲明類型是 DecoratingProxy
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 透明 且 聲明類型是個接口 且 聲明類型是 Advised
else if (!this.advised.opaque && method.getDeclaringClass().isInterface()
&& method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
/**
* 如果設置了 exposeProxy = true 則將代理對象設置到線程本地變量中
*
* @see org.springframework.context.annotation.EnableAspectJAutoProxy#exposeProxy()
**/
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
/**
* 獲取此方法的攔截鏈
**/
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
/**
* 檢查是否有其他通知
* 如果沒有,可以依靠目標直接反射調用,並避免創建 MethodInvocation
**/
if (chain.isEmpty()) {
/**
* 我們可以跳過創建 MethodInvocation 的操作:僅直接調用目標
* 請注意,最終的調用者必須是 InvokerInterceptor,因此我們知道它僅對目標執行反射操作,並且不執行熱插拔或花哨代理
**/
// 使給定參數適應給定方法中的目標籤名
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 通過反射調用給定目標
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
/**
* 創建一個 ReflectiveMethodInvocation
**/
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
/**
* 通過攔截器鏈進入連接點【責任鏈模式】
**/
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class
&& returnType.isInstance(proxy)
&& !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException();
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
和AOP的調用過程一樣,先去AdvisedSupport的getInterceptorsAndDynamicInterceptionAdvice()
獲取攔截器鏈,沒有則直接反射調用目標方法。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method,
@Nullable Class<?> targetClass) {
/**
* 目標對象方法的緩存鍵
*
* public abstract void com.ambition.service.PayService.pay()
**/
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 先去緩存中獲取
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 緩存中沒有,則進行邏輯解析
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
// 放入緩存中
this.methodCache.put(cacheKey, cached);
}
return cached;
}
DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice()
方法將增強器轉換爲攔截器,而TransactionInterceptor本身就是一個攔截器:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config,
Method method,
@Nullable Class<?> targetClass) {
// 獲取 DefaultAdvisorAdapterRegistry 實例
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 獲取通知
Advisor[] advisors = config.getAdvisors();
// 攔截器集合
List<Object> interceptorList = new ArrayList<>(advisors.length);
// 目標類
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
/**
* 是 PointcutAdvisor 切點通知類
* BeanFactoryTransactionAttributeSourceAdvisor 符合條件
* DefaultPointcutAdvisor 符合條件
* InstantiationModelAwarePointcutAdvisorImpl 符合條件
**/
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
/**
* 代理配置以預先過【默認爲False】 或者 切面與目標類匹配
*
* 事務的類過濾器是 TransactionAttributeSourceClassFilter
**/
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
/**
* 獲取方法匹配器
*
* 事務的是
* TransactionAttributeSourcePointcut
*
* AOP 的是
* TrueMethodMatcher
* AspectJExpressionPointcut
**/
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
/**
* TrueMethodMatcher 不是 IntroductionAwareMethodMatcher 的子類
* AspectJExpressionPointcut 是 IntroductionAwareMethodMatcher 的子類
* TransactionAttributeSourcePointcut 不是 IntroductionAwareMethodMatcher 的子類
**/
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
// 匹配
if (match) {
// 轉換爲攔截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
// 封裝爲 InterceptorAndDynamicMethodMatcher
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 是 IntroductionAdvisor 類型
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
看過上一篇AOP源碼解析的客官一定知道主要看的還是getInterceptors()
方法,matches()
方法上面我們已經看過了,重複代碼就不看了。
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
/**
* ExposeInvocationInterceptor 是 MethodInterceptor
* AspectJAfterThrowingAdvice 是 MethodInterceptor
* AspectJAfterAdvice 是 MethodInterceptor
* AspectJAroundAdvice 是 MethodInterceptor
* AspectJAroundAdvice 是 MethodInterceptor
*
* TransactionInterceptor 是 MethodInterceptor
**/
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
有攔截器鏈就封裝ReflectiveMethodInvocation,調用proceed()
方法:
public Object proceed() throws Throwable {
/**
* 從索引 -1 開始並提前增加【通過遞歸調用】
* 確保所有的責任者都完成處理邏輯
**/
// 是最後一個攔截器
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 直接通過反射調用目標方法
return invokeJoinpoint();
}
/**
* 獲取下一個責任者
*
* AOP的攔截器
* ExposeInvocationInterceptor
* AspectJAfterThrowingAdvice
* AfterReturningAdviceInterceptor
* AspectJAfterAdvice
* AspectJAroundAdvice
* MethodBeforeAdviceInterceptor
*
* 事務的攔截器
* TransactionInterceptor
**/
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
/**
* 是 InterceptorAndDynamicMethodMatcher 類型
* 這裏都不是這個類型
**/
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
/**
* 動態評估方法匹配,靜態部分都已經進行了評估並發現已匹配
**/
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
/**
* Dynamic matching failed. Skip this interceptor and invoke the next in the chain.
*
* 動態匹配失敗,跳過此攔截器並調用鏈中的下一個攔截器
**/
return proceed();
}
}
else {
/**
* 它是一個攔截器,因此只需要調用它,切入點將在構造此對象之前進行靜態評估
**/
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
然後就進入到TransactionInterceptor的invoke()
方法中:
public Object invoke(MethodInvocation invocation) throws Throwable {
/**
* 處理目標方法,可能爲空
* 應該將 TransactionAttributeSource 和目標類以及方法(可能來自接口)傳遞給它
*
* class com.ambition.service.PayServiceImpl
**/
Class<?> targetClass =
(invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
return invokeWithinTransaction(
// 目標方法
invocation.getMethod(),
// 目標類
targetClass,
// 返回
invocation::proceed
);
}
前方高能,事務比AOP複雜的地方就在於執行流程上
protected Object invokeWithinTransaction(Method method,
@Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// reactiveAdapterRegistry 爲空
if (this.reactiveAdapterRegistry != null) {
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter != null) {
return new ReactiveTransactionSupport(adapter).invokeWithinTransaction(method, targetClass, invocation);
}
}
/**
* 如果 transaction 屬性爲 null,則該方法爲非事務處理
*
* 獲取事務屬性源【AnnotationTransactionAttributeSource】
**/
TransactionAttributeSource tas = getTransactionAttributeSource();
// 獲取事務屬性值【RuleBasedTransactionAttribute】
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 確定事務管理器【配置文件注入的DataSourceTransactionManager】
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
/**
* 獲取連接點標識
* 僅限於 TransactionAttribute 是 DefaultTransactionAttribute 類型
* 這裏是 RuleBasedTransactionAttribute
* @see AbstractFallbackTransactionAttributeSource#getTransactionAttribute(java.lang.reflect.Method, java.lang.Class)
**/
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// DataSourceTransactionManager 不是 CallbackPreferringPlatformTransactionManager 類型
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
/**
* 使用 getTransaction 和 commit / rollback 調用進行標準事務劃分
*
* 如果需要則創建事務【DefaultTransactionStatus】
**/
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
/**
* 這是一個環繞通知:調用鏈中的下一個攔截器
* 這通常會導致目標對象被調用
**/
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
/**
* 目標調用異常,需要則進行回滾
**/
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
/**
* 不管是否發生異常,都要還原舊事物的 TransactionInfo
**/
cleanupTransactionInfo(txInfo);
}
......
/**
* 提交事務
**/
commitTransactionAfterReturning(txInfo);
return retVal;
}
......
}
先來看一下第一個比較重要的createTransactionIfNecessary()
方法:
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr,
final String joinpointIdentification) {
/**
* 如果未指定名稱,則將方法標識用作事務名稱
**/
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 獲取 TransactionStatus
status = tm.getTransaction(txAttr);
}
......
}
// 將給定屬性和狀態對象封裝爲 TransactionInfo 對象
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
其實就是將事務管理器和事務屬性值封裝爲TransactionInfo對象,再將事務狀態設置進去,比較重要的是getTransaction()
獲取事務狀態方法:
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
/**
* 如果未提供 TransactionDefinition,則使用默認 StaticTransactionDefinition
**/
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 獲取事務對象【DataSourceTransactionObject】
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 是已存在的事務【事務方法嵌套調用事務方法時才成立】
if (isExistingTransaction(transaction)) {
/**
* 找到現有事務,則檢查傳播行爲以瞭解行爲
**/
return handleExistingTransaction(def, transaction, debugEnabled);
}
/**
* 檢查新事務的定義設置【超時時間是否有效】
**/
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
/**
* 找不到現有事務,檢查傳播行爲以查找如何進行
**/
/**
* 支持當前事務,但是當前事務傳播行爲不存在,則引發異常
*
* 這裏是 PROPAGATION_REQUIRED 或者 PROPAGATION_REQUIRES_NEW
**/
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException();
}
// 判斷事務的傳播行爲
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED
|| def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW
|| def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
/**
* 掛起給定的事務
*
* 現在還不需要掛起,此時爲空
**/
SuspendedResourcesHolder suspendedResources = suspend(null);
try {
/**
* 是否需要激活同步
*
* transactionSynchronization 爲 SYNCHRONIZATION_ALWAYS 值爲0
* SYNCHRONIZATION_NEVER 值爲2
**/
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 創建 DefaultTransactionStatus 事務狀態對象
DefaultTransactionStatus status = newTransactionStatus(
def,
transaction,
true,
newSynchronization,
debugEnabled,
suspendedResources
);
// 開啓事務準備工作
doBegin(transaction, def);
// 初始化事務同步
prepareSynchronization(status, def);
return status;
}
catch (RuntimeException | Error ex) {
// 異常則恢復掛起的事務
resume(null, suspendedResources);
throw ex;
}
}
......
}
如果事務的傳播行爲符合條件,會先根據需要掛起事務,Spring這裏用了很多線程安全的ThreadLocal緩存來保存事務同步、當前事務名稱、當前事務只讀狀態、當前事務隔離級別等屬性值。
我理解的所謂準備工作,其實就是將連接持有器綁定到線程上,掛起就是創建一個SuspendedResourcesHolder掛起資源持有器保存一下當前的屬性值,然後去執行另一個事務方法,然後再解除資源綁定,獲取之前的掛起資源持有器,恢復使其繼續執行,如果另一個事務發生異常會傳播到上一個事務中。
來看一下doBegin()
方法:
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 沒有連接持有器 或者 持有器與事務同步
if (!txObject.hasConnectionHolder()
|| txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// 獲取當前使用的數據源的連接【JDBC4Connection】
Connection newCon = obtainDataSource().getConnection();
// 設置一個新的連接持有器
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
// 設置持有器與事務同步
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
// 獲取連接
con = txObject.getConnectionHolder().getConnection();
// 使用給定的事務處理連接,獲取之前的隔離級別,此時爲空
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
/**
* 如有必要,請切換爲手動提交
* 在某些 JDBC 驅動程序中,這是非常昂貴的,因此不必要的時候我們不想這樣做
* (例如,如果我們已經明確配置了連接池以進行設置)
**/
// 如果是自動提交
if (con.getAutoCommit()) {
// 必須還原自動提交
txObject.setMustRestoreAutoCommit(true);
// 設置爲手動提交
con.setAutoCommit(false);
}
// 準備事務連接
prepareTransactionalConnection(con, definition);
// 設置連接持有者的事務爲活動的且由 JDBC 管理的事務
txObject.getConnectionHolder().setTransactionActive(true);
// 確定超時時間【默認超時時間】
int timeout = determineTimeout(definition);
// 如果不是默認超時,則設置超時時間【單位秒】
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// 是新的連接持有器
if (txObject.isNewConnectionHolder()) {
// 綁定連接持有器到線程上
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException();
}
}
可以看到基本上的邏輯就是我上面所說的,那麼createTransactionIfNecessary()
方法就說這麼多了,具體的還有很多代碼,我覺得不是特別重要,大家自己跟進去看一下。
proceedWithInvocation()
方法就是調用攔截器鏈中的下一個攔截器方法,異常回滾的completeTransactionAfterThrowing()
方法最後調用的就是ConnectionImpl的rollback()
方法,
提交事務的commitTransactionAfterReturning()
方法最後調用的就是ConnectionImpl的commit()
方法,這些都太底層了,不是Spring的源碼, 有興趣的可以自己看一下。
現在是晚上十一點多,肝了幾天終於肝完了,原創不易,喜歡的大佬可以點贊收藏,咱們下一篇再見。