本文轉自「天河聊技術」微信公衆號spring
說在前面微信
基於註解的spring聲明式事務管理源碼解析已經完畢了,第一篇文章中提到spring事務管理模式有兩種形式一種是proxy,一種是aspectj,基於proxy已經解析完畢了,默認的也是proxy,聲明式事務管理配置一種是基於註解,一種是基於xml配置文件的,最後再補充下基於aspectj這種事務模式和基於xml配置的聲明式事務管理的源碼解析。app
正文ide
基於aspectj的聲明事務管理模式源碼解析ui
找到這個方法org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parsethis
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 註冊事務監聽器工廠 registerTransactionalEventListenerFactory(parserContext); // 獲取模式屬性 String mode = element.getAttribute("mode"); if ("aspectj".equals(mode)) { // mode="aspectj" registerTransactionAspect(element, parserContext); } else { // mode="proxy" AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext); } return null; }
if ("aspectj".equals(mode)) { // mode="aspectj" registerTransactionAspect(element, parserContext);
進入到這個方法spa
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#registerTransactionAspectorm
private void registerTransactionAspect(Element element, ParserContext parserContext) { String txAspectBeanName = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME; String txAspectClassName = TransactionManagementConfigUtils.TRANSACTION_ASPECT_CLASS_NAME; if (!parserContext.getRegistry().containsBeanDefinition(txAspectBeanName)) { RootBeanDefinition def = new RootBeanDefinition(); def.setBeanClassName(txAspectClassName); def.setFactoryMethodName("aspectOf"); // 註冊事務管理器到bean定義中 registerTransactionManager(element, def); // 註冊AnnotationTransactionAspect bean定義 parserContext.registerBeanComponent(new BeanComponentDefinition(def, txAspectBeanName)); } }
進入到這個類xml
org.springframework.transaction.aspectj.AnnotationTransactionAspect對象
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect { public AnnotationTransactionAspect() { // 初始化註解事務資源 super(new AnnotationTransactionAttributeSource(false)); } /** * Matches the execution of any public method in a type with the Transactional將類型中的任何公共方法的執行與事務匹配 * annotation, or any subtype of a type with the Transactional annotation.註釋,或具備事務註釋的類型的任何子類型。 */ private pointcut executionOfAnyPublicMethodInAtTransactionalType() : execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *); /** * Matches the execution of any method with the Transactional annotation.將任何方法的執行與事務註釋匹配。 */ private pointcut executionOfTransactionalMethod() : execution(@Transactional * *(..)); /** * Definition of pointcut from super aspect - matched join points從超方面匹配的鏈接點定義切入點 * will have Spring transaction management applied.將應用Spring事務管理。 */ protected pointcut transactionalMethodExecution(Object txObject) : (executionOfAnyPublicMethodInAtTransactionalType() || executionOfTransactionalMethod() ) && this(txObject); }
基於aop標籤配置的聲明式事務源碼解析
找到這個方法
org.springframework.transaction.config.TxAdviceBeanDefinitionParser#doParse
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { // 構造事務管理器對象 builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element)); // 獲取<tx:attributes>子節點 List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT); // 只能有一個<tx:attributes>節點 if (txAttributes.size() > 1) { parserContext.getReaderContext().error( "Element <attributes> is allowed at most once inside element <advice>", element); } else if (txAttributes.size() == 1) { // Using attributes source. Element attributeSourceElement = txAttributes.get(0); // 解析<tx:attributes>標籤 RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext); builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition); } else { // Assume annotations source. builder.addPropertyValue("transactionAttributeSource", new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource")); } }
private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) { // 獲取<tx:method子節點 List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT); ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap = new ManagedMap<>(methods.size()); transactionAttributeMap.setSource(parserContext.extractSource(attrEle)); for (Element methodEle : methods) { // 獲取name屬性 String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE); TypedStringValue nameHolder = new TypedStringValue(name); nameHolder.setSource(parserContext.extractSource(methodEle)); RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute(); // 獲取事務傳播機制 String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE); // 獲取事務隔離級別 String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE); // 獲取事務超時參數 String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE); // 獲取事務只讀屬性 String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE); if (StringUtils.hasText(propagation)) { attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation); } if (StringUtils.hasText(isolation)) { attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation); } if (StringUtils.hasText(timeout)) { try { attribute.setTimeout(Integer.parseInt(timeout)); } catch (NumberFormatException ex) { parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle); } } if (StringUtils.hasText(readOnly)) { attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE))); } List<RollbackRuleAttribute> rollbackRules = new LinkedList<>(); if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) { // 獲取事務回滾的異常配置 String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE); addRollbackRuleAttributesTo(rollbackRules,rollbackForValue); } if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) { // 獲取不回滾事務的異常類型 String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE); addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue); } attribute.setRollbackRules(rollbackRules); transactionAttributeMap.put(nameHolder, attribute); } RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class); attributeSourceDefinition.setSource(parserContext.extractSource(attrEle)); attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap); return attributeSourceDefinition; }
private void addRollbackRuleAttributesTo(List<RollbackRuleAttribute> rollbackRules, String rollbackForValue) { // 能夠配置多個異常,用,分開 String[] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(rollbackForValue); for (String typeName : exceptionTypeNames) { rollbackRules.add(new RollbackRuleAttribute(StringUtils.trimWhitespace(typeName))); } } private void addNoRollbackRuleAttributesTo(List<RollbackRuleAttribute> rollbackRules, String noRollbackForValue) { // 能夠配置多個異常,用,分開 String[] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(noRollbackForValue); for (String typeName : exceptionTypeNames) { rollbackRules.add(new NoRollbackRuleAttribute(StringUtils.trimWhitespace(typeName))); } }
下面的邏輯都同樣了,都走的是一個事務攔截器攔截事務方法,解析事務屬性,開啓事務進行提交或者回滾。
說到最後
本次解析僅表明我的看法,僅供參考。