声明:本文是自己在学习spring注解事务处理源代码时所留下的笔记; 难免有错误,敬请读者谅解!!!

1、事务注解标签

    <tx:annotation-driven />

2、tx 命名空间解析器 
事务tx命名空间解析器TxNamespaceHandler 
org.springframework.transaction.config.TxNamespaceHandler#init

3、AnnotationDrivenBeanDefinitionParser#parse 解析事务标签

(1)、以下方法的核心逻辑主要是选择是否使用 Aspect 方式实现代理,默认方式为 JDK 的动态代理。 
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse

public BeanDefinition parse(Element element, ParserContext parserContext) {String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) {// mode="aspectj"registerTransactionAspect(element, parserContext);}else {// mode="proxy"   注意 AopAutoProxyConfigurer 为当前内的内部类AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null;
}

(2)、进入如下方法,该方法的核心逻辑通过硬编码的方式配置 Aop 动态代理的解析器 
AopAutoProxyConfigurer#configureAutoProxyCreator 
通过硬编码,Spring 为我们定义了如下的 Spring BeanDefinition 对象 
(a)、AnnotationTransactionAttributeSource.class 事务注解属性解析器BeanDefinition 对象。 
AnnotationTransactionAttributeSource 构造方法会初始化:

public AnnotationTransactionAttributeSource() {this(true);
}public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {this.publicMethodsOnly = publicMethodsOnly;this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);this.annotationParsers.add(new SpringTransactionAnnotationParser());// @Transactional 注解解析器if (ejb3Present) {this.annotationParsers.add(new Ejb3TransactionAnnotationParser());// Ejb 解析器}

(b)、TransactionInterceptor.class 事务拦截器BeanDefinition 对象 
(c)、BeanFactoryTransactionAttributeSourceAdvisor.class 事务切面解析器 
(d)、TransactionInterceptor.class 事务拦截器BeanDefinition 对象 
(e)、容易忽略的第一行代码:AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); 在这个方法内部 Spring 为我们的注入了:InfrastructureAdvisorAutoProxyCreator.class 

private static class AopAutoProxyConfigurer {public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {// 非常重要的一行代码,在这个里面注册了:InfrastructureAdvisorAutoProxyCreator.class 该类实现了Spring BeanProcessor 的扩展接口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(AnnotationTransactionAttributeSource.class);// 事务注解解析器sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// Create the TransactionInterceptor definition.RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);//事务拦截器interceptorDef.setSource(eleSource);interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// Create the TransactionAttributeSourceAdvisor definition.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);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));parserContext.registerComponent(compositeDef);}}
}

4、Spring Bean 实例化创建代理对象 
(a)、AbstractAutowireCapableBeanFactory#initializeBean(Java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

(b)、AbstractAutoProxyCreator#postProcessAfterInitialization 

还记得上面我们提到的 InfrastructureAdvisorAutoProxyCreator 的类图吧,最后我们的 @Transactional 注解的类会执行该类中的 postProcessAfterInitialization 方法

(c)、Bean 的初始化后置处理,通过注释可以了解到,当前方法处理后会返回一个 bean 的代理对象

/*** Create a proxy with the configured interceptors if the bean is* identified as one to proxy by the subclass.* @see #getAdvicesAndAdvisorsForBean*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.containsKey(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);// 创建代理类的核心方法}}return bean;
}

(d)、AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.   获取切面   获取的过程是一个非常复杂的过程Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 创建代理对象,默认的情况下会使用 JDK 的动态代理接口创建代理对象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;
}

(c)、获取到的事务切面 

(d)、事务切面获取逻辑 

(e)、委托 ProxyFactory 创建代理对象

protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {ProxyFactory proxyFactory = new ProxyFactory();// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.proxyFactory.copyFrom(this);if (!shouldProxyTargetClass(beanClass, beanName)) {// Must allow for introductions; can't just set interfaces to// the target's interfaces only.Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);for (Class<?> targetInterface : targetInterfaces) {proxyFactory.addInterface(targetInterface);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);for (Advisor advisor : advisors) {proxyFactory.addAdvisor(advisor);}proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 最终会使用:JdkDynamicAopProxy  创建事务的Aop 代理对象return proxyFactory.getProxy(this.proxyClassLoader);
}

(f)、最终生成代理对象 

5、代理类执行 
JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {MethodInvocation invocation;Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Class<?> targetClass = null;Object target = null;try {// 如果目标方法没有实现equalsif (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.return equals(args[0]);}// 如果目标方法没有实现hashcodeif (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// The target does not implement the hashCode() method itself.return hashCode();}// 根据代理对象的配置来调用服务if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {// Service invocations on ProxyConfig with the proxy config...return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal;if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// May be null. Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.// 获取目标对象target = targetSource.getTarget();if (target != null) {targetClass = target.getClass();}// 获取定义好的拦截器链// Get the interception chain for this method.List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// Check whether we have any advice. If we don't, we can fallback on direct// reflective invocation of the target, and avoid creating a MethodInvocation.if (chain.isEmpty()) {// We can skip creating a MethodInvocation: just invoke the target directly// Note that the final invoker must be an InvokerInterceptor so we know it does// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.// 没有拦截链则直接调用target方法retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);}else {// We need to create a method invocation...//对拦截链进行封装  得到对象ReflectiveMethodInvocation 调用 proceed 方法invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();// 方法内部将执行拦截器的切面直到目标方法被执行}// Massage return value if necessary.Class<?> returnType = method.getReturnType();if (retVal != null && retVal == target && returnType.isInstance(proxy) &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {// Special case: it returned "this" and the return type of the method// is type-compatible. Note that we can't help if the target sets// a reference to itself in another returned object.retVal = proxy;}else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);}return retVal;}finally {if (target != null && !targetSource.isStatic()) {// Must have come from TargetSource.targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}
}

7、代理会执行到: ReflectiveMethodInvocation#proceed 方法

8、最终会执行到:TransactionInterceptor#invoke 方法

9、执行 TransactionAspectSupport 事务方法 
TransactionInterceptor#invoke 方法会调用到父类的 TransactionAspectSupport#invokeWithinTransaction 方法

10、业务方法执行 

11、Spring 事务处理的流程 

(a)、开启事务 

(b)、事务回滚 

(c)、事务提交 

http://blog.csdn.net/dalinsi/article/details/53203540

声明:本编文章是自己在查看spring提取@Transactional注解的源码过程中随手记下的笔记,只做了大概流程的记录,未做详细分析,如有错误还请谅解。

1、事务切面匹配处理类

AopUtils#canApply(Pointcut, Class , boolean) 
方法中会调用到 TransactionAttributeSourcePointcut#matches 方法

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));classes.add(targetClass);for (Class<?> clazz : classes) {Method[] methods = clazz.getMethods();for (Method method : methods) {//methodMatcher.matches(method, targetClass) 方法会匹配对应的处理类,在Transaction提取的过程中会匹配到:TransactionAttributeSourcePointcut if ((introductionAwareMethodMatcher != null &&introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||methodMatcher.matches(method, targetClass)) {return true;}}}return false;
}

2、事务切点匹配

TransactionAttributeSourcePointcut#matches

在阅读TransactionAttributeSourcePointcut内的源代码的时候,我们发现该类是一个抽象,但是他确没有实现的子类!!!那么这个类到底在哪被引用了呢?

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {public boolean matches(Method method, Class targetClass) {// 该处调用了 getTransactionAttributeSource() 的抽象方法,但是却没有子类实现这个方法,这是怎么一回事呢?TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}@Overridepublic boolean equals(Object other) {if (this == other) {return true;}if (!(other instanceof TransactionAttributeSourcePointcut)) {return false;}TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());}@Overridepublic int hashCode() {return TransactionAttributeSourcePointcut.class.hashCode();}@Overridepublic String toString() {return getClass().getName() + ": " + getTransactionAttributeSource();}/*** Obtain the underlying TransactionAttributeSource (may be {@code null}).* To be implemented by subclasses.*/protected abstract TransactionAttributeSource getTransactionAttributeSource();}

3、TransactionAttributeSourcePointcut 抽象类的应用

我们怀着上面的疑问全局搜索 TransactionAttributeSourcePointcut 可以在 BeanFactoryTransactionAttributeSourceAdvisor 里面找到如下的代码:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {private TransactionAttributeSource transactionAttributeSource;// 此处利用了匿名内部类的方式实例化了 TransactionAttributeSourcePointcut 对象,在此我们找到了上面问题的答案。private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Overrideprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};/*** Set the transaction attribute source which is used to find transaction* attributes. This should usually be identical to the source reference* set on the transaction interceptor itself.* @see TransactionInterceptor#setTransactionAttributeSource*/public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {this.transactionAttributeSource = transactionAttributeSource;}/*** Set the {@link ClassFilter} to use for this pointcut.* Default is {@link ClassFilter#TRUE}.*/public void setClassFilter(ClassFilter classFilter) {this.pointcut.setClassFilter(classFilter);}public Pointcut getPointcut() {return this.pointcut;}}

3、TransactionAttributeSource 属性的 Bean 定义过程

其实,在实例化 BeanFactoryTransactionAttributeSourceAdvisor 时,Spring 已经为我们的 BeanFactoryTransactionAttributeSourceAdvisor 设置了 TransactionAttributeSource 属性,可以进入 AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator 方法中看源代码:

private static class AopAutoProxyConfigurer {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);// 注解事务 transactionAttributeSource Spring 定义的Bean为: AnnotationTransactionAttributeSource 实例// Create the TransactionAttributeSource definition.RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationTransactionAttributeSource.class);sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// Create the TransactionInterceptor definition.RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// create BeanFactoryTransactionAttributeSourceAdvisor Bean 的定义// Create the TransactionAttributeSourceAdvisor definition.RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);// 设置 transactionAttributeSource 属性advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));parserContext.registerComponent(compositeDef);}}
}

4、TransactionAttributeSource#getTransactionAttribute 方法的调用过程

通过以上的分析,我们可以确定 
TransactionAttributeSourcePointcut#getTransactionAttributeSource 返回的是:AnnotationTransactionAttributeSource 实例,AnnotationTransactionAttributeSource继承自:AbstractFallbackTransactionAttributeSource, 故此TransactionAttributeSourcePointcut#matches 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {public boolean matches(Method method, Class targetClass) {TransactionAttributeSource tas = getTransactionAttributeSource();// 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}// 省略其他代码 ……………………
}

再看 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法

// 获取事务属性
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {// First, see if we have a cached value.Object cacheKey = getCacheKey(method, targetClass);Object cached = this.attributeCache.get(cacheKey);if (cached != null) {// Value will either be canonical value indicating there is no transaction attribute,// or an actual transaction attribute.if (cached == NULL_TRANSACTION_ATTRIBUTE) {return null;}else {return (TransactionAttribute) cached;}}else {// We need to work it out.  根据 method、targetClass 推算事务属性,TransactionAttribute TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);// Put it in the cache.if (txAtt == null) {this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);}else {if (logger.isDebugEnabled()) {logger.debug("Adding transactional method '" + method.getName() + "' with attribute: " + txAtt);}this.attributeCache.put(cacheKey, txAtt);}return txAtt;}
}

5、事务属性的推算过程:

// 推算事务属性,TransactionAttribute
private TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {// Don't allow no-public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// Ignore CGLIB subclasses - introspect the actual user class.Class<?> userClass = ClassUtils.getUserClass(targetClass);// 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 = ClassUtils.getMostSpecificMethod(method, userClass);// If we are dealing with method with generic parameters, find the original method.specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);// 通过上面的分析,findTransactionAttribute 该方法最终会调用到:AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.Class<?>) // First try is the method in the target class. 方式1: 从目标类的方法上找 Transaction注解TransactionAttribute txAtt = findTransactionAttribute(specificMethod);if (txAtt != null) {return txAtt;}// Second try is the transaction attribute on the target class.  方式2: 从目标类上找 Transaction注解txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());if (txAtt != null) {return txAtt;}if (specificMethod != method) {// 以上两种方式如果还没有找到 TransactionAttribute 属性,那就要从目标类的接口开始找// Fallback is to look at the original method.  方式3:接口的方法上找 Transaction注解txAtt = findTransactionAttribute(method);if (txAtt != null) {return txAtt;}// Last fallback is the class of the original method.  方式4:接口的类上找 Transaction注解return findTransactionAttribute(method.getDeclaringClass());}return null;
}

6、事务注解属性的解析

AnnotationTransactionAttributeSource#findTransactionAttribute(Java.lang.Class

7、获取事务注解

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {//获取 Transactional 注解Transactional ann = AnnotationUtils.getAnnotation(ae, Transactional.class);if (ann != null) {//从 @Transactional 注解上获取事务属性值,并包装成 TransactionAttribute 返回return parseTransactionAnnotation(ann);}else {return null;}}public TransactionAttribute parseTransactionAnnotation(Transactional ann) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();rbta.setPropagationBehavior(ann.propagation().value());rbta.setIsolationLevel(ann.isolation().value());rbta.setTimeout(ann.timeout());rbta.setReadOnly(ann.readOnly());rbta.setQualifier(ann.value());ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();Class[] rbf = ann.rollbackFor();for (Class rbRule : rbf) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}String[] rbfc = ann.rollbackForClassName();for (String rbRule : rbfc) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}Class[] nrbf = ann.noRollbackFor();for (Class rbRule : nrbf) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}String[] nrbfc = ann.noRollbackForClassName();for (String rbRule : nrbfc) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}rbta.getRollbackRules().addAll(rollBackRules);return rbta;}@Overridepublic boolean equals(Object other) {return (this == other || other instanceof SpringTransactionAnnotationParser);}@Overridepublic int hashCode() {return SpringTransactionAnnotationParser.class.hashCode();}}

http://blog.csdn.net/dalinsi/article/details/53215041

转载于:https://www.cnblogs.com/softidea/p/6854982.html

Spring提取@Transactional事务注解的源码解析相关推荐

  1. @Transactional的用法详解及Transactional事务无效的源码分析

    数据库事务正确执行的四要素 1.原子性 事务是不可分割的最小的工作单元,事务内的操作要么全做,要么全不做,不能只做一部分. 2.一致性 事务执行前数据库的数据按照逻辑处于正确的状态,事务执行后数据库的 ...

  2. spring MVC cors跨域实现源码解析

    spring MVC cors跨域实现源码解析 名词解释:跨域资源共享(Cross-Origin Resource Sharing) 简单说就是只要协议.IP.http方法任意一个不同就是跨域. sp ...

  3. redis watchdog_Redis分布式事务框架Redisson源码解析(一)

    代码片段一. public static void main(String[] args) throws Exception { Config config = new Config(); confi ...

  4. Spring Security Core 5.1.2 源码解析 -- PasswordEncoderFactories

    概述 PasswordEncoderFactories是Spring Security创建DelegatingPasswordEncoder对象的工厂类.该工厂所创建的DelegatingPasswo ...

  5. Spring源码解析之-- 事务TransactionInterceptor 分析(开启事务)

    目录 一.介绍 二.TransactionInterceptor 分析 2. 流程 2.1 invoke 2.1.1 TransactionAspectSupport#invokeWithinTran ...

  6. Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析

      基于最新Spring 5.x,详细介绍了Spring 事务源码,包括< tx:annotation-driven/>标签源码解析.   此前我们已经学习了Spring的<tx:a ...

  7. Spring源码深度解析(郝佳)-Spring 常用注解使用及源码解析

      我们在看Spring Boot源码时,经常会看到一些配置类中使用了注解,本身配置类的逻辑就比较复杂了,再加上一些注解在里面,让我们阅读源码更加难解释了,因此,这篇博客主要对配置类上的一些注解的使用 ...

  8. @Import注解:导入配置类的四种方式源码解析

    微信搜索:码农StayUp 主页地址:https://gozhuyinglong.github.io 源码分享:https://github.com/gozhuyinglong/blog-demos ...

  9. Spring 定时任务源码解析

    日常的开发中我们经常需要开发一些定时任务,比较常见的是 Spring 自带的定时任务,使用简单方便,不需要另外引进一些其他 Jar 包. 今天我们来简单的了解一下,看看 Spring 的定时任务是怎么 ...

最新文章

  1. VS2010 CUDA 5.5 Win7 64位配置以及项目创建配置
  2. TokuDB · 引擎特性 · HybridDB for MySQL高压缩引擎TokuDB 揭秘
  3. android studio文件风格,Android Studio构建风格 – 如何拥有不同风格的相同源文件
  4. 对于刷oj时因为scanf()出现wa而cin却AC的详解 【scanf() 和 cin 详解】
  5. 【kruskal重构树】【主席树】werewolf 狼人(P4899)
  6. mysql 触发器 运算符_mysql三元运算,上下连表,视图,触发器,存储过程,事务等不常用方法...
  7. 邢台职业技术学院计算机系宿舍,邢台职业技术学院宿舍条件怎么样 男生女生宿舍图片...
  8. UGUI 与 Spine 的完美结合
  9. 通过分析nginx的日志来过滤出访问过于频繁的IP地址,然后添加到nginx的blockip.conf,并重启nginx...
  10. 《C陷阱与缺陷》读书笔记与总结
  11. python计算快递运费价格表_python实现快递价格查询系统
  12. DDR3 数据传输 (三)
  13. 根据浏览器获取经纬度
  14. Flash player 必要的系统组件未能正常运行,请修复Adobe Flash Player
  15. oracle数据表空间与数据文件,oracle的表空间及数据文件
  16. matlab ifft取实部,[合集] matlab中IFFT的问题
  17. Wrapper中ge,gt,lt,le的含义
  18. 云栖大会:两万人参会 十大亮点抢先看
  19. 为什么九大头部APP都选择U-APM 应用性能监控平台?
  20. Reflex WMS入门系列二十三:几个库存相关的报表

热门文章

  1. 旅游风景展示应用源码iPad版
  2. 【驱动笔记9】初探IRP
  3. Maven 之常用命令
  4. n阶乘的c语言代码,求10000的阶乘(c语言代码实现)
  5. 设计模式复习-状态模式
  6. UVA10881蚂蚁
  7. POJ3041 最小顶点覆盖
  8. C语言经典例13-水仙花数
  9. 【Netty】反应器 Reactor 模式 ( 单反应器 Reactor 单线程 | 单反应器 Reactor 多线程 )
  10. [BZOJ5292][BJOI2018]治疗之雨(概率DP+高斯消元)