一、tx的解析和bean的Aop代理
<tx:annotation-driven transaction-manager="transactionManager"/>
- 針對namespace就行判斷,判斷是bean標籤還是自定義標籤(除了bean的其他標籤)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
這個毫無疑問是進入delegate.parseCustomElement(ele);
這裏面進行自定義標籤的解析
- 獲取對應namespace的處理器
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
通過分析,tx的解析器是TxNamespaceHandler
- 獲取annotation-driven的解析器
handler.parse中首選就是獲取對應的解析器
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionParser parser = findParserForElement(element, parserContext);
return (parser != null ? parser.parse(element, parserContext) : null);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
String localName = parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
最終得知是AnnotationDrivenBeanDefinitionParser
進行解析。
- 開始真正的解析
public BeanDefinition parse(Element element, ParserContext parserContext) {
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
//沒想到spring也會直接寫某個字符串(印象中都是通過一個static變量進行定義的)
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
registerJtaTransactionAspect(element, parserContext);
}
}
else {
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
- 註冊和事務有關的BeanPostProcessor和事務有關的攔截器等
保留核心代碼
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
// Create the TransactionAttributeSource definition.(事務的屬性配置)
RootBeanDefinition sourceDef = new RootBeanDefinition( "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
// Create the TransactionInterceptor definition.(事務方法攔截器)
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
// Create the TransactionAttributeSourceAdvisor definition.(這就是一個advisor,一個advisor可以包含一個攔截器)
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
}
}
從這裏就可以看出來spring的事務管理其實就是Aop的一個典型應用
點擊AOP源碼分析 ,來獲取更詳細的信息
- advisorDef :從aop的源碼分析可知,一個advisor可看成是一個應用pointCut的通知(類似前置或者後置等通知),創建單例的時候比如JDK代理,會有一個invocationHandler(或者說Cglib會又至少一個callback),在這裏其實TransactionInterceptor 就是真正的攔截實現類
- TransactionInterceptor :真正的攔截實現類
- TransactionAttributeSource:這個就是解析xml或者annotation中的配置
重點分析一下TransactionAttributeSource
它的核心邏輯是存在AbstractFallbackTransactionAttributeSource
中的getTransactionAttribute
方法中
//getTransactionAttribute會調用這個方法
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// Second try is the transaction attribute on the target class.
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
簡單來說會從目標類的方法上需要事務註解,如果沒有找到就從接口中去尋找。
現在advisor有了,但是還缺少一個生成代理的契機,比如某個切面的pointcut命中了某個bean,在哪個bean初始化後,在AnotationAwareAspectJAutoProxyCreator後置處理器的postProcessAfterInitialization方法中就創建了這個bean的代理。
現在我們也缺少一個後置處理器。其實這上面這個 方法的第一句話
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
就是做這樣的事情
public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
}
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
最後發現InfrastructureAdvisorAutoProxyCreator
出現了這個類,和AnotationAwareAspectJAutoProxyCreator
有些類似
分析UML圖後發現確實是個BeanPostProcessor。好了到了這裏Spring事務的bean的代理生成已經分析完畢。
二、事務攔截器的分析
切入點是TransactionInterceptor
。
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
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)) {
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
}
- tas: 這個就是前面解析的時候的
TransactionAttributeSource
- tm :這個就比較複雜了。先看PlatformTransactionManagerUML圖
頂級接口PlatformTransactionManager是jdbc事務管理和jta事務的頂級接口。大部分邏輯是在AbstractPlatformTransactionManager
就完成了,剩下的一些模板方法就是在DataSourceTransactionManager
和JtaTransactionManager
中的doxxx方法中。
DataSourceTransactionManager
:基本可以看出是單一數據庫的事務管理
JtaTransactionManager
:多數據庫的事務管理器,他還有另外一個高大上的名字分佈式事務的實現
下面重點分析下面這句話
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
從名字上看如果需要就創建事務信息,如果不需要就利用當前線程已經存在的事務。
方法createTransactionIfNecessary
主要是調用getTransaction
方法
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
}
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// Check definition settings for new transaction.
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
在方法doGetTransaction
中
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());//核心就是這句話
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
在TransactionSynchronizationManager.getResource(obtainDataSource())中就是獲取數據庫的連接了。
getResource方法主要是利用ThreadLocal變量獲取連接
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
這樣如果當前線程已經存在線程,肯定可以從當前線程獲取到jdbc的連接,這樣新的事務和老的事務就公用了一個connection了。這就是傳播行爲Propagation.REQUIRED
把兩個事務合成一個事務就行管理的關鍵了,也很容易理解回滾的時候,可以同時回滾了,因爲利用的是同一個connnection。
未完待續