接着看我们的自动创建代理器是如何创建的:
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element)
public static void registerAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); } private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) { if (beanDefinition != null) { // 注册的 beanName 是 org.springframework.aop.config.internalAutoProxyCreator parserContext.registerComponent( new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME)); } }
在这一步中,注册了一个 beanName
是 org.springframework.aop.config.internalAutoProxyCreator
的 bean
:InfrastructureAdsivorAutoProxyCreator
,下图是它的继承体系图:
infrastructrue_advisor_auto_proxy_creator_diagram
可以看到,它实现了 InstantiationAwareBeanPostProcessor
这个接口,也就是说在 Spring
容器中,所有 bean
实例化时,Spring
都会保证调用其 postProcessAfterInitialization
方法。
与上一篇介绍的 AOP
代理器一样,在实例化 bean
的时候,调用了代理器父类 AbstractAutoProxyCreator
的 postProcessAfterInitialization
方法:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { // 组装 key Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 如果适合被代理,则需要封装指定的 bean return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
其中关于 wrapIfNecessory
方法,在上一篇 AOP
中已经详细讲过,这里讲下这个方法做了什么工作:
- 找出指定 `bean` 对应的增强器
- 根据找出的增强器创建代理
与创建 AOP
代理相似的过程就不再重复说,讲下它们的不同点:
判断目标方法是否适合 canApply
AopUtils#canApply(Advisor, Class, boolean)
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } }
我们在前面看到,TransactionAttributeSourceAdvisor
的父类是 PointcutAdvisor
,所以在目标方法判断的时候,会取出切点信息 pca.getPointcut()
。
我们之前注入的切面类型 bean
是 AnnotationTransactionAttributeSource
,通过下面的方法包装,最后返回对象类型是 TransactionAttributeSourcePointcut
的切点信息
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override @Nullable protected TransactionAttributeSource getTransactionAttributeSource() { // 实现父类的方法,在子类中进行了扩展,返回之前在标签注册时的AnnotationTransactionAttributeSource return transactionAttributeSource; } };
匹配标签 match
在匹配 match
操作中,区别的是 AOP
识别的是 @Before
、@After
,而我们的事务 TX
识别的是 @Transactional
标签。
判断是否是事务方法的入口方法在这:
org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches
@Override public boolean matches(Method method, Class<?> targetClass) { // 事务切点匹配的方法 TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); }
那它到底到哪一步解析事务注解的呢,继续跟踪代码,答案是:
AnnotationTransactionAttributeSource#determineTransactionAttribute
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) { for (TransactionAnnotationParser parser : this.annotationParsers) { TransactionAttribute attr = parser.parseTransactionAnnotation(element); if (attr != null) { return attr; } } return null; }
在这一步中,遍历注册的注解解析器进行解析,由于我们关注的是事务解析,所以直接定位到事务注解的解析器:
SpringTransactionAnnotationParser#parseTransactionAnnotation(AnnotatedElement)
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { // 解析事务注解的属性 AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes( element, Transactional.class, false, false); if (attributes != null) { return parseTransactionAnnotation(attributes); } else { return null; } }
首先判断是否含有 @Transactional
注解,如果有的话,才继续调用 parse
解析方法:
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); // 注释 9.4 解析事务注解的每一个属性 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; }
小结
通过上面的步骤,完成了对应类或者方法的事务属性解析。
主要步骤在于寻找增强器,以及判断这些增强器是否与方法或者类匹配。
如果某个 bean
属于可被事务增强时,也就是适用于增强器 BeanFactoryTransactionAttributeSourceAdvisor
进行增强。
之前我们注入了 TransactionInterceptor
到 BeanFactoryTransactionAttributeSourceAdvisor
中,所以在调用事务增强器增强的代理类时,会执行 TransactionInterceptor
进行增强。同时,也就是在 TransactionInterceptor
类中的 invoke
方法中完成整个事务的逻辑。
运行
事务增强器 TransactionInterceptor
TransactionInterceptor
支撑着整个事务功能的架构。跟之前 AOP
的 JDK
动态代理 分析的一样,TransactionInterceptor
拦截器继承于 MethodInterceptor
,所以我们要从它的关键方法 invoke()
看起:
public Object invoke(MethodInvocation invocation) throws Throwable { // 注释 9.5 执行事务拦截器,完成整个事务的逻辑 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }
实际调用了父类的方法:TransactionAspectSupport#invokeWithinTransaction
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // 如果transaction属性为null,则该方法是非事务性的 TransactionAttributeSource tas = getTransactionAttributeSource(); // 获取对应事务属性 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); // 获取事务管理器 final PlatformTransactionManager tm = determineTransactionManager(txAttr); // 构造方法唯一标识(类.方法) final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // 声明式事务处理 // 标准事务划分 : 使用 getTransaction 和 commit / rollback 调用 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal; try { //传入的是回调函数对象:invocation.proceed。 执行被增强的方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // 异常回滚 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // 清除信息 cleanupTransactionInfo(txInfo); } // 提交事务 commitTransactionAfterReturning(txInfo); return retVal; } else { // 编程式事务处理 final ThrowableHolder throwableHolder = new ThrowableHolder(); // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); ... return result; } } }
贴出的代码有删减,简略了错误异常的 try / catch
和编程式事务处理的逻辑。因为我们更多使用到的是声明式事务处理,就是在 XML
文件配置或者 @Transactional
注解编码,实际通过 AOP
实现,而编程式事务处理是通过 Transaction Template
实现,比较少使用到,所以省略了这部分处理代码。
事务管理器
通过该方法,确定要用于给定事务的特定事务管理器
TransactionAspectSupport#determineTransactionManager
protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) { // Do not attempt to lookup tx manager if no tx attributes are set // 注释 9.6 寻找事务管理器 if (txAttr == null || this.beanFactory == null) { // 如果没有事务属性或者 BeanFactory 为空时,从缓存里面寻找 return asPlatformTransactionManager(getTransactionManager()); } String qualifier = txAttr.getQualifier(); // 如果注解配置中指定了事务管理器,直接取出使用 if (StringUtils.hasText(qualifier)) { return determineQualifiedTransactionManager(this.beanFactory, qualifier); } else if (StringUtils.hasText(this.transactionManagerBeanName)) { return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName); } else { // 上面步骤都没找到,最后才去容器中,根据 className 来寻找 PlatformTransactionManager defaultTransactionManager = asPlatformTransactionManager(getTransactionManager()); ... return defaultTransactionManager; } }
由于最开始我们在 XML
文件中配置过 transactionManager
属性,所以该方法在我们例子中将会返回类型是 DataSourceTransactionManager
的事务管理器,下面是 DataSourceTransactionManager
的继承体系:
它实现了 InitializingBean
接口,不过只是在 afterPropertiesSet()
方法中,简单校验 dataSource
是否为空,不细说这个类。
事务开启
TransactionAspectSupport#createTransactionIfNecessary
protected TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) { // 如果没有名称指定则使用方法唯一标识,并使用 DelegatingTransactionAttribute 包装 txAttr 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); } } // 根据指定的属性与 status 准备一个 TransactionInfo return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
在创建事务方法中,主要完成以下三件事:
- 使用 `DelegatingTransactionAttribute` 包装 `txAttr` 实例
- 获取事务:`tm.getTransaction(txAttr)`
- 构建事务信息:`prepareTransactionInfo(tm, txAttr, joinpointIdentification, status)`
核心方法在第二点和第三点,分别摘取核心进行熟悉。
获取 TransactionStatus
status = tm.getTransaction(txAttr);
由于代码较长,直接来总结其中几个关键点
获取事务
创建对应的事务实例,我们使用的是 DataSourceTransactionManager
中的 doGetTransaction
方法,创建基于 JDBC
的事务实例。
protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); // 如果当前线程已经记录数据库链接则使用原有链接 ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource()); // false 表示非新创建连接 txObject.setConnectionHolder(conHolder, false); return txObject; }
其中在同一个线程中,判断是否有重复的事务,是在 TransactionSynchronizationManager.getResource(obtainDataSource())
中完成的,关键判断逻辑是下面这个:
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources"); private static Object doGetResource(Object actualKey) { Map<Object, Object> map = resources.get(); if (map == null) { return null; } Object value = map.get(actualKey); // Transparently remove ResourceHolder that was marked as void... if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) { map.remove(actualKey); // Remove entire ThreadLocal if empty... if (map.isEmpty()) { resources.remove(); } value = null; } return value; }
结论:resources
是一个 ThreadLocal
线程私有对象,每个线程独立存储,所以判断是否存在事务,判断的依据是当前线程、当前数据源(DataSource)中是否存在活跃的事务 - map.get(actualKey)
。
处理已经存在的事务
根据前面说的,判断当前线程是否存在事务,判断依据为当前线程记录的连接不为空且连接中(connectionHolder)中的 transactionActive
属性不为空,如果当前线程存在事务,将根据不同的事务传播特性进行处理。具体代码逻辑如下:
if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. // 当前线程存在事务,分情况进行处理 return handleExistingTransaction(def, transaction, debugEnabled); }
PROPAGATION_NEVER
在配置中配置设定为 PROPAGATION_NEVER
,表示该方法需要在非事务的环境下运行,但处于事务处理的状态(可能是外部带事务的方法调用了非事务的方法),将会抛出异常:
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); }
PROPAGATION_NOT_SUPPORTED
如果有事务存在,将事务挂起,而不是抛出异常:
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { Object suspendedResources = suspend(transaction); boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus( definition, null, false, newSynchronization, debugEnabled, suspendedResources); }