spring 事务 XML
事务就是AOP的很典型的应用。(原来需要自己写代码前开启关闭事务,现在通过spring的配置) 所以必要要有<aop:config>,<aop:config>里面要有<aop:pointcut>,<aop:pointcut>就是拦截的表达式(匹配哪些方法要拦截),还要有<aop:advisor>这是切面,切面里面要有pointcut-ref, advice-ref。advice-ref是一个增强,这个增强在事务里面就是对拦截的方法进行开始关闭事务(AOP的增强就是执行before,after,around方法)就是前置后置增强, 事务的开启关闭挂起,都是通过JDBC的事务开启关闭嵌套实现的。
public interface AA { public void purchase(int isbn) ; }
public class BookShopXMLService implements AA{ @Autowired private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void purchase(int isbn) { jdbcTemplate.update("update aa set name='5' where id=?", isbn); // int x = 1/0; jdbcTemplate.update("update aa set name='6' where id=?", isbn); } }
public class Test2 { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:config" + "/spring/applicationContext-core.xml"); AA as = (AA) context.getBean("bookShopXMLService"); as.purchase(1); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 导入外部属性文件 --> <context:property-placeholder location="classpath*:config/core/core.properties" /> <!-- 数据库连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置jdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="bookShopXMLService" class="cn.sdut.xml.BookShopXMLService"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事务通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 配置要添加事务的方法 --> <tx:attributes> <!-- 给purchase方法添加事务 --> <tx:method name="purchase" propagation="REQUIRED" isolation="READ_COMMITTED" /> </tx:attributes> </tx:advice> <!-- 配置AOP --> <aop:config proxy-target-class="false"> <!-- 配置切入点表达式 --> <aop:pointcut expression="execution(* cn.sdut.xml.BookShopXMLService.*(..))" id="pointcut" /> <!-- 将事务通知和切入点表达式关联起来 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config> </beans>
<tx:advice id="userTxAdvice" transaction-manager="transactionManager"> 增强 <tx:attributes> <tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" isolation="DEFAULT"/> <tx:method name="saveTest" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" isolation="DEFAULT"/> <tx:method name="saveTest1" propagation="NESTED" read-only="false" rollback-for="java.lang.RuntimeException" isolation="DEFAULT"/> <tx:method name="delete*" propagation="NESTED" read-only="false" rollback-for="java.lang.RuntimeException"/> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException"/> <tx:method name="check*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException"/> <tx:method name="print*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException"/> <tx:method name="*" propagation="REQUIRED" read-only="false" isolation="DEFAULT" rollback-for="java.lang.RuntimeException"/> </tx:attributes> </tx:advice>
<aop:config proxy-target-class="false"> <aop:pointcut id="pc" expression="execution(public * com.zhuguang.jack.service..*.*(..))"/> <aop:advisor pointcut-ref="pc" advice-ref="userTxAdvice"/> 增强(对public * com.zhuguang.jack.service..*.*(..)目标方法的增强,就是开启事务关闭事务,对应的就是前置后置增强,就是环绕增强,前面是开始事务后面是关闭事务,) </aop:config>
<tx:advice>是增强。做了哪些工作。 public class TxNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser()); //解析</tx:advice>标签。 registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser()); } }
TxAdviceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser extends AbstractBeanDefinitionParser //解析<tx:advice>标签, public final BeanDefinition parse(Element element, ParserContext parserContext) { //element = tx:advice AbstractBeanDefinition definition = parseInternal(element, parserContext); // tx:advice的bean定义,//解析<tx:attributes>,<tx:method>子标签,TransactionInterceptor, if (definition != null && !parserContext.isNested()) { try { String id = resolveId(element, definition, parserContext); //解析id属性 if (!StringUtils.hasText(id)) { parserContext.getReaderContext().error(ment); } String[] aliases = new String[0]; String name = element.getAttribute(NAME_ATTRIBUTE);//name if (StringUtils.hasLength(name)) { aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name)); } BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases); //TransactionInterceptor, registerBeanDefinition(holder, parserContext.getRegistry()); // tx:advice的bean定义注册到spring容器。 } } return definition; }
//解析<tx:attributes>,<tx:method>子标签, protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); //BeanDefinitionBuilder里面有GenericBeanDefinition,GenericBeanDefinition的beanClass属性为TransactionInterceptor, String parentName = getParentName(element); if (parentName != null) { builder.getRawBeanDefinition().setParentName(parentName); } Class<?> beanClass = getBeanClass(element); //TransactionInterceptor,是真正实例化的, if (beanClass != null) { builder.getRawBeanDefinition().setBeanClass(beanClass); //设置GenericBeanDefinition的beanClass属性为TransactionInterceptor, } builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); doParse(element, parserContext, builder); //解析,builder = BeanDefinitionBuilder。element = tx:advice,//解析<tx:attributes>,<tx:method>子标签, return builder.getBeanDefinition(); //GenericBeanDefinition }
public static BeanDefinitionBuilder genericBeanDefinition() { BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); builder.beanDefinition = new GenericBeanDefinition(); //返回的就是这个GenericBeanDefinition return builder; }
//解析<tx:attributes>,<tx:method>子标签, protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { //把属性加到TransactionInterceptor里面去, builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element)); List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT); //拿到<tx:attributes>属性, if (txAttributes.size() > 1) { //只能有一个<tx:attributes>属性, parserContext.getReaderContext().error(at most once inside element <advice>", element); } else if (txAttributes.size() == 1) { Element attributeSourceElement = txAttributes.get(0); //<tx:attributes> RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext); //解析<tx:method>子标签 builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition); } }
public BeanDefinitionBuilder addPropertyReference(String name, String beanName) { this.beanDefinition.getPropertyValues().add(name, new RuntimeBeanReference(beanName)); //IOC的时候去实例化, return this; }
//解析<tx:method>子标签, private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) { List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT); //拿到<tx:method>子标签。<tx:method name="purchase" propagation="REQUIRED" isolation="READ_COMMITTED" />拦截purchase方法,aop:pointcut已经做了拦截,这里再拦截,之后指定的方法才会有事务, ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap = new ManagedMap<TypedStringValue, RuleBasedTransactionAttribute>(methods.size()); transactionAttributeMap.setSource(parserContext.extractSource(attrEle)); for (Element methodEle : methods) { 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 attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation); } if (StringUtils.hasText(isolation)) {//设置到attribute attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation); } if (StringUtils.hasText(timeout)) { try { attribute.setTimeout(Integer.parseInt(timeout));//设置到attribute } } if (StringUtils.hasText(readOnly)) {//设置到attribute attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE))); } List<RollbackRuleAttribute> rollbackRules = new LinkedList<RollbackRuleAttribute>(); //事务回滚,遇到异常回滚,异常有很多,rollback-for就是遇到这个异常就回滚,no-rollback-for就是遇到这个异常不回滚。 if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) { String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE); addRollbackRuleAttributesTo(rollbackRules,rollbackForValue);//添加rollback-for到rollbackRules, } if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) { String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE); addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue);//添加no-rollback-for到rollbackRules, } attribute.setRollbackRules(rollbackRules);//rollback-for,no-rollback-for添加到属性attribute transactionAttributeMap.put(nameHolder, attribute); //属性跟方法绑定, } RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class); //bean定义(事务的属性), attributeSourceDefinition.setSource(parserContext.extractSource(attrEle)); attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap); return attributeSourceDefinition; }
Spring事物传播行为 事务嵌套 PROPAGATION_REQUIRED(默认)—如果当前有事务,就用当前事务(就使用外层的事务,不使用自己的事务),如果当前没有事务,就新建一个事务。这是最常见的选择。 PROPAGATION_SUPPORTS--支持当前事务(外层事务),如果当前没有事务,就以非事务方式执行。//如果外层方法没有事务,就会以非事务进行执行。 PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常(使用外层事务)。 PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起(不用外层事务,就跟外层没有影响了)。 PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起(失效)。(外层有事务,就已非事务执行,外层事务失效) PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。 默认传播行为为REQUIRED
事务的隔离级别:spring的隔离级别(一个事务不能读到另一个没有提交的事务的数据,事务就是加锁),数据库的隔离级别。
<!-- 配置AOP --> <aop:config> <!-- 配置切入点表达式 --> <aop:pointcut expression="execution(* cn.sdut.xml.BookShopXMLService.*(..))" id="pointcut" /> <!-- 将事务通知和切入点表达式关联起来 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config>
解析aop:config标签。 public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); configureAutoProxyCreator(parserContext, element); List<Element> childElts = DomUtils.getChildElements(element); for (Element elt: childElts) { String localName = parserContext.getDelegate().getLocalName(elt); if (POINTCUT.equals(localName)) { parsePointcut(elt, parserContext); } else if (ADVISOR.equals(localName)) { parseAdvisor(elt, parserContext); } else if (ASPECT.equals(localName)) { parseAspect(elt, parserContext); } } return null; }
解析aop:pointcut标签: private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) { pointcutDefinition = createPointcutDefinition(expression); String pointcutBeanName = id; parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); //AspectJExpressionPointcut添加到spring的容器, return pointcutDefinition; }
解析aop:advisor标签: private void parseAdvisor(Element advisorElement, ParserContext parserContext) { AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext); //DefaultBeanFactoryPointcutAdvisor添加到spring容器, String id = advisorElement.getAttribute(ID); try { this.parseState.push(new AdvisorEntry(id)); String advisorBeanName = id; if (StringUtils.hasText(advisorBeanName)) { parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef); } Object pointcut = parsePointcutProperty(advisorElement, parserContext); //pointcut属性, if (pointcut instanceof BeanDefinition) { advisorDef.getPropertyValues().add(POINTCUT, pointcut); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut)); } else if (pointcut instanceof String) { advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut)); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef)); } } }
解析tx:advice标签就是把GenericBeanDefinition加到spring的容器,解析aop:config标签就是把AspectJExpressionPointcut和DefaultBeanFactoryPointcutAdvisor加到spring容器。
解析bookShopXMLService(事务也是AOP的实现之一), createBean-----resolveBeforeInstantiation protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName); } } return bean; }
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } } return null; }
AbstractAutoProxyCreator类: public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); //BookShopXMLService,bookShopXMLService,返回null。 if (targetSource != null) { this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } } return null; }
protected boolean shouldSkip(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //DefaultBeanFactoryPointcutAdvisor for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor) { if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) { return true; } } } return super.shouldSkip(beanClass, beanName); }
public List<Advisor> findAdvisorBeans() { String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; //DefaultBeanFactoryPointcutAdvisor就是<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />标签, } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name)) { else { try { advisors.add(this.beanFactory.getBean(name, Advisor.class)); //创建DefaultBeanFactoryPointcutAdvisor实例, } } } } } return advisors; //DefaultBeanFactoryPointcutAdvisor }
doCreateBean-----initializeBean-----applyBeanPostProcessorsAfterInitialization, public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName);//返回jdk动态代理:[ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)]; targetSource [[BookShopXMLService]]; if (result == null) { return result; } } return result; }
AbstractAutoProxyCreator: public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); //返回jdk动态代理:[ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)]; targetSource [[BookShopXMLService]]; } } return bean; }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);//[ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)] if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); //返回jdk的动态代理,[ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)]; targetSource [[BookShopXMLService]]; this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } }
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);//[ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)] if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //DefaultBeanFactoryPointcutAdvisor, List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); //解析advice-ref属性, if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors;//[ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类) ] }
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { MethodMatcher methodMatcher = pc.getMethodMatcher(); //AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..)), IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; //AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..)), } Set<Class<?>> classes = new HashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass);//[class cn.sdut.xml.BookShopXMLService] for (Class<?> clazz : classes) { Method[] methods = clazz.getMethods(); for (Method method : methods) {//public void cn.sdut.xml.BookShopXMLService.purchase(int), if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || //YES,TRUE methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) { checkReadyToMatch(); Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); //public void cn.sdut.xml.BookShopXMLService.purchase(int),class cn.sdut.xml.BookShopXMLService。返回public void cn.sdut.xml.BookShopXMLService.purchase(int)。 ShadowMatch shadowMatch = getShadowMatch(targetMethod, method); //YES,TRUE if (shadowMatch.alwaysMatches()) { return true; } }
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) { ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod); //null,shadowMatchCache = {}, if (shadowMatch == null) { synchronized (this.shadowMatchCache) { Method methodToMatch = targetMethod; //public void cn.sdut.xml.BookShopXMLService.purchase(int)。 PointcutExpression fallbackPointcutExpression = null; shadowMatch = this.shadowMatchCache.get(methodToMatch);//null, if (shadowMatch == null) {// try { shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod); //YES,TRUE } } } } return shadowMatch; //YES,TRUE }
public ShadowMatch matchesMethodExecution(Method aMethod) { //public void cn.sdut.xml.BookShopXMLService.purchase(int), ShadowMatch match = matchesExecution(aMethod); //YES,TRUE return match; }
private ShadowMatch matchesExecution(Member aMember) { Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember, this.matchContext);//method-execution(void cn.sdut.xml.BookShopXMLService.purchase(int)), ShadowMatchImpl sm = getShadowMatch(s); //YES,TRUE sm.setSubject(aMember); sm.setWithinCode(null); sm.setWithinType(aMember.getDeclaringClass()); return sm; //YES,TRUE }
private ShadowMatchImpl getShadowMatch(Shadow forShadow) {//forShadow = method-execution(void cn.sdut.xml.BookShopXMLService.purchase(int)), org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);//return FuzzyBoolean.YES; Test residueTest = Literal.TRUE; ExposedState state = getExposedState(); if (match.maybeTrue()) { residueTest = pointcut.findResidue(forShadow, state); //TRUE } ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters); sm.setMatchingContext(this.matchContext); return sm;//YES,TRUE }
public final FuzzyBoolean match(Shadow shadow) { if (shadow.getKind().isSet(couldMatchKinds())) { ret = matchInternal(shadow);//return FuzzyBoolean.YES; } lastMatchedShadowId = shadow.shadowId; lastMatchedShadowResult = ret; return ret;//return FuzzyBoolean.YES; } protected FuzzyBoolean matchInternal(Shadow shadow) { if (!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(), this.kind == Shadow.MethodCall)) { if (kind == Shadow.MethodCall) { warnOnConfusingSig(shadow); } return FuzzyBoolean.NO; } return FuzzyBoolean.YES; }
protected void extendAdvisors(List<Advisor> candidateAdvisors) { AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);//candidateAdvisors = DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice'。开始解析<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />标签里面的advice-ref属性。 }
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) { if (!advisors.isEmpty()) { //DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)。 boolean foundAspectJAdvice = false; for (Advisor advisor : advisors) { if (isAspectJAdvice(advisor)) { foundAspectJAdvice = true; } } if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) { advisors.add(0, ExposeInvocationInterceptor.ADVISOR); return true; } } return false; }
public Advice getAdvice() { synchronized (this.adviceMonitor) { if (this.advice == null && this.adviceBeanName != null) { this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class); //adviceBeanName = txAdvice,获取txAdvice实例。this = DefaultBeanFactoryPointcutAdvisor, } return this.advice; } }
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory);//beanClass = class cn.sdut.xml.BookShopXMLService, } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor);//advisors = [ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)] } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.proxyClassLoader); //proxyFactory里面有[ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))]; advice bean 'txAdvice' = advice = TransactionInterceptor(<tx:advice>标签解析成的类)]; targetSource [[BookShopXMLService]]; }
方法的调用: AA as = (AA) context.getBean("bookShopXMLService"); //as是jdk的动态代理,cn.sdut.xml.BookShopXMLService@e6516e,里面的h = JdkDynamicAopProxy@6c9fed53,h里面的advised = ProcyFactory = ProxyFactory: 2 advisors [ExposeInvocationInterceptor.ADVISOR, DefaultBeanFactoryPointcutAdvisor: pointcut [AspectJExpressionPointcut: () execution(* BookShopXMLService.*(..))]; advice bean 'txAdvice' = TransactionInterceptor@5aabbb29]; targetSource [BookShopXMLService@e6516e]]; as.purchase(1);
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //advised = ProxyFactory,method = AA.purchase(int),targetClass = class cn.sdut.xml.BookShopXMLService。拿到所有的MeathodIntesept。返回ExposeInvocationInterceptor@548e76f1, TransactionInterceptor@5aabbb29, else { invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //proxy = BookShopXMLService,target = BookShopXMLService,method = AA.purchase(int),args = [1],targetClass = BookShopXMLService,chain = ExposeInvocationInterceptor@548e76f1, TransactionInterceptor@5aabbb29, retVal = invocation.proceed(); //链式调用,invocation = ReflectiveMethodInvocation: public abstract void cn.sdut.xml.AA.purchase(int); target is of class [cn.sdut.xml.BookShopXMLService], } Class<?> returnType = method.getReturnType(); return retVal; } }
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) { MethodCacheKey cacheKey = new MethodCacheKey(method); List<Object> cached = this.methodCache.get(cacheKey); if (cached == null) { cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass); //this = ProxyFactory, this.methodCache.put(cacheKey, cached); } return cached;//ExposeInvocationInterceptor@548e76f1, TransactionInterceptor@5aabbb29, }
public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, Class<?> targetClass) { //config = ProxyFactory,method = AA.purchase(int),targetClass = BookShopXMLService, List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length); boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); //fasle, AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); for (Advisor advisor : config.getAdvisors()) { if (advisor instanceof PointcutAdvisor) {//ExposeInvocationInterceptor.ADVISOR,DefaultBeanFactoryPointcutAdvisor, PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { MethodInterceptor[] interceptors = registry.getInterceptors(advisor);//TransactionInterceptor@5aabbb29 MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();//AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..)) if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { if (mm.isRuntime()) { } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } } return interceptorList; //ExposeInvocationInterceptor@548e76f1, TransactionInterceptor@5aabbb29, }
private static boolean hasMatchingIntroductions(Advised config, Class<?> targetClass) { //config = ProxyFactory,targetClass = BookShopXMLService。 for (int i = 0; i < config.getAdvisors().length; i++) {//ExposeInvocationInterceptor.ADVISOR,DefaultBeanFactoryPointcutAdvisor(TransactionInterceptor@5aabbb29,AspectJExpressionPointcut: () execution(* cn.sdut.xml.BookShopXMLService.*(..))) Advisor advisor = config.getAdvisors()[i];//ExposeInvocationInterceptor.ADVISOR(不走),DefaultBeanFactoryPointcutAdvisor(不走), if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (ia.getClassFilter().matches(targetClass)) { return true; } } } return false; }
public Object proceed() throws Throwable { //interceptorsAndDynamicMethodMatchers = ExposeInvocationInterceptor@548e76f1, TransactionInterceptor@5aabbb29,this = ReflectiveMethodInvocation: public abstract void cn.sdut.xml.AA.purchase(int); target is of class [cn.sdut.xml.BookShopXMLService] if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //ExposeInvocationInterceptor@548e76f1, if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { } else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
ExposeInvocationInterceptor@548e76f1的invoke方法: public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); //null invocation.set(mi); //mi = ReflectiveMethodInvocation: public abstract void cn.sdut.xml.AA.purchase(int); target is of class [cn.sdut.xml.BookShopXMLService] try { return mi.proceed(); //又进去,链式调用第二个 } finally { invocation.set(oldInvocation); } }
public Object proceed() throws Throwable { if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint();//调用目标方法, } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //TransactionInterceptor@5aabbb29, if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { } else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
//TransactionInterceptor@5aabbb29类的invoke, public Object invoke(final MethodInvocation invocation) throws Throwable {//invocation = ReflectiveMethodInvocation: public abstract void cn.sdut.xml.AA.purchase(int); target is of class [cn.sdut.xml.BookShopXMLService], Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); //class cn.sdut.xml.BookShopXMLService return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { return invocation.proceed(); //又调进去,invocation = ReflectiveMethodInvocation, } }); }
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) { final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);//getTransactionAttributeSource() = {purchase=PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED},根据方法的名字拿到这个方法对应的事务属性(隔离级别,传播属性,事务回滚的异常,只读事务),返回PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED final PlatformTransactionManager tm = determineTransactionManager(txAttr); //事务管理,transactionManager管理开启关闭事务,dataSource是一个连接池(java,sql,connection),一切事务都是基于连接来做的, final String joinpointIdentification = methodIdentification(method, targetClass); //当前被调用的方法cn.sdut.xml.BookShopXMLService.purchase, if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); //开启事务,tm = DataSourceTransactionManager,txAttr = PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED。joinpointIdentification = BookShopXMLService.purchase,返回事务信息(有管理平台,事务属性,老的事务信息)。 Object retVal = null; try { retVal = invocation.proceedWithInvocation();//调到上面invokeWithinTransaction的匿名对象的方法去了。又走链式调用,就调到目标方法去了。 } catch (Throwable ex) {//目标方法有异常,事务回滚。 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; } }
protected TransactionInfo createTransactionIfNecessary( PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) { TransactionStatus status = null; if (txAttr != null) { if (tm != null) { status = tm.getTransaction(txAttr); //txAttr = PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED。开启了事务了。 } } return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);//准备事务的信息, }
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); //返回的对象里面有connection,DataSourceTransactionManager$DataSourceTransactionObject, if (definition == null) { definition = new DefaultTransactionDefinition(); //PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED(事务传播属性,事务隔离级别,回滚异常), } if (isExistingTransaction(transaction)) {//是否已经存在事务,不是第一次进来。方法嵌套就会有事务的嵌套。 return handleExistingTransaction(definition, transaction, debugEnabled); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources = suspend(null); //挂起事务(挂起外层方法的事务),第一次进来没有事务,就是空事务,返回null, try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //事务状态, doBegin(transaction, definition); //开启事务,transaction = DataSourceTransactionManager$DataSourceTransactionObject,definition = PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED。 prepareSynchronization(status, definition);//同步 return status; //返回事务状态, } } } }
protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); //里面有connection,DataSourceTransactionObject 就是事务对象(标明当前事务是否是最新的事务,connectionHolder里面有connectionHandler里面有connection)。 txObject.setSavepointAllowed(isNestedTransactionAllowed()); //是否允许嵌套事务, ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource); //dataSource = 数据库连接池,第一次是空的, txObject.setConnectionHolder(conHolder, false); return txObject; }
protected void doBegin(Object transaction, TransactionDefinition definition) { //开启事务, DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { //第一次进来是空,会去连接池里面拿到一个对象。 Connection newCon = this.dataSource.getConnection(); //拿到一个连接, txObject.setConnectionHolder(new ConnectionHolder(newCon), true); //连接塞到事务对象中,并且是新的, } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); //就是前面从连接池拿到的连接, Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);//返回隔离级别, txObject.setPreviousIsolationLevel(previousIsolationLevel);//隔离级别塞到事务对象中, if (con.getAutoCommit()) {//连接中自动提交为true, txObject.setMustRestoreAutoCommit(true); con.setAutoCommit(false);//连接的自动提交设置为false。开启事务。 } txObject.getConnectionHolder().setTransactionActive(true);//事务是活动的设置为true, if (txObject.isNewConnectionHolder()) {//是不是新的ConnectionHolder, TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); } } }
public static Integer prepareConnectionForTransaction(Connection con, TransactionDefinition definition) { if (definition != null && definition.isReadOnly()) { con.setReadOnly(true);//设置只读 } Integer previousIsolationLevel = null; if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { int currentIsolation = con.getTransactionIsolation(); //拿到数据库隔离级别, if (currentIsolation != definition.getIsolationLevel()) {//数据库的隔离级别和spring的隔离级别不一样, previousIsolationLevel = currentIsolation; con.setTransactionIsolation(definition.getIsolationLevel());//就把spring的隔离级别设置成当前连接的隔离级别, } } return previousIsolationLevel;//返回隔离级别, }
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm, TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) { TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification); //包装了事务的一些信息(事务管理平台,事务的属性,pointcut), if (txAttr != null) { txInfo.newTransactionStatus(status);//事务的状态塞到txInfo里面去, } else { } txInfo.bindToThread(); return txInfo; }
private void bindToThread() { this.oldTransactionInfo = transactionInfoHolder.get(); //老的事务信息, transactionInfoHolder.set(this);//当前事务信息塞到ThreadLocal中去, }
protected void commitTransactionAfterReturning(TransactionInfo txInfo) { if (txInfo != null && txInfo.hasTransaction()) { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());//提交事务 } } public final void commit(TransactionStatus status) throws TransactionException { DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;//事务状态 processCommit(defStatus); }
private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { try { else if (status.isNewTransaction()) { doCommit(status); } } } finally { cleanupAfterCompletion(status); } }
protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); try { con.commit();//拿到连接进行commit, } }
目标方法有异常,事务回滚。 protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.hasTransaction()) {//有事务,事务状态不为空, if (txInfo.transactionAttribute.rollbackOn(ex)) {//异常是 RuntimeException || Error都会回滚, try { txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); } } else {//异常不是 RuntimeException || Error就不回滚,就会提交。 try { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } } } }
public final void rollback(TransactionStatus status) throws TransactionException { if (status.isCompleted()) { throw new IllegalTransactionStateException(n"); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;//拿到事务状态, processRollback(defStatus); }
private void processRollback(DefaultTransactionStatus status) { try { try { triggerBeforeCompletion(status); if (status.hasSavepoint()) { //嵌套事务,有savepoint, status.rollbackToHeldSavepoint(); } else if (status.isNewTransaction()) { //是一个新事物 doRollback(status); } else if (status.hasTransaction()) { if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) { doSetRollbackOnly(status); } else { } } } triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); } finally { cleanupAfterCompletion(status); } }
protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); try { con.rollback();//拿到连接, } } public void rollbackToHeldSavepoint() throws TransactionException { getSavepointManager().rollbackToSavepoint(getSavepoint()); setSavepoint(null); }
方法嵌套就会有事务的嵌套。 private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled){ if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {//事务的传播属性 } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {//事务的传播属性,是新事务, SuspendedResourcesHolder suspendedResources = suspend(transaction);//挂起前面的事务, try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, definition);//外层方法的事务挂起了,这里开一个内层方法的事务, prepareSynchronization(status, definition); return status; } } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {//事务的传播属性,是嵌套 if (useSavepointForNestedTransaction()) { DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);//状态, status.createAndHoldSavepoint();//设置savepoint, return status; } else { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } if (isValidateExistingTransaction()) { } boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {//挂起前面的事务, if (TransactionSynchronizationManager.isSynchronizationActive()) {//事务是活动的, List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization(); try { Object suspendedResources = null; if (transaction != null) { suspendedResources = doSuspend(transaction); } String name = TransactionSynchronizationManager.getCurrentTransactionName(); TransactionSynchronizationManager.setCurrentTransactionName(null); boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); TransactionSynchronizationManager.setCurrentTransactionReadOnly(false); Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null); boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive(); TransactionSynchronizationManager.setActualTransactionActive(false); return new SuspendedResourcesHolder( suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive); } } }
protected Object doSuspend(Object transaction) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; txObject.setConnectionHolder(null); ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.unbindResource(this.dataSource); return conHolder; }
方法的嵌套,事务的嵌套。(内部和外部方法的连接connection是不一样的,) begin transation = TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); try { retVal = invocation.proceedWithInvocation(); public void saveTest(String param) { String sql = "insert into test(num) values (?)"; int count = jdbcTemplate.update(sql, new Object[]{param}); begin transation = TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); try { retVal = invocation.proceedWithInvocation(); myService.saveTest1(param);(因为myService是jdk的动态代理,所以又会走进去),如果这里有异常, } catch (Throwable ex) { completeTranactionAfterThrowing(txInfo, ex); //回滚,又把异常抛出来了, throw ex;//内部方法的异常跑出来之后,被外部方法捕获到了, } commit transaction = commitTransactionAfterReturning(txInfo);//里面方法有异常之后,这个提交就执行不到了。所以内部的方法根本就没有提交,而是回滚了。 } } catch (Throwable ex) {//内部方法的异常跑出来之后,被外部方法捕获到了,所以外部方法也没有提交,而是回滚了。(所以要在内部的方法要自己捕获异常), completeTranactionAfterThrowing(txInfo, ex); //事务回滚, throw ex; } commit transaction = commitTransactionAfterReturning(txInfo);//事务提交