spring5 源码深度解析----- Spring事务 是怎么经过AOP实现的?(100%理解Spring事务)

做者:chen_haophp

 

 

正文java

此篇文章须要有SpringAOP基础,知道AOP底层原理能够更好的理解Spring的事务处理。spring

自定义标签

对于Spring中事务功能的代码分析,咱们首先从配置文件开始人手,在配置文件中有这样一个配置:<tx:annotation-driven/>。能够说此处配置是事务的开关,若是没有此处配置,那么Spring中将不存在事务的功能。那么咱们就从这个配置开始分析。编程

根据以前的分析,咱们所以能够判断,在自定义标签中的解析过程当中必定是作了一些辅助操做,因而咱们先从自定义标签入手进行分析。使用Idea搜索全局代码,关键字annotation-driven,最终锁定类TxNamespaceHandler,在TxNamespaceHandler中的 init 方法中:数组

  •  
@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}

在遇到诸如tx:annotation-driven为开头的配置后,Spring都会使用AnnotationDrivenBeanDefinitionParser类的parse方法进行解析。缓存

  •  
@Override@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) {registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");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;}

在解析中存在对于mode属性的判断,根据代码,若是咱们须要使用AspectJ的方式进行事务切入(Spring中的事务是以AOP为基础的),那么可使用这样的配置:app

  •  
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

注册 InfrastructureAdvisorAutoProxyCreator

咱们以默认配置为例进行分析,进人AopAutoProxyConfigurer类的configureAutoProxyCreator:框架

  •  
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {//向IOC注册InfrastructureAdvisorAutoProxyCreator这个类型的BeanAopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {Object eleSource = parserContext.extractSource(element);
// Create the TransactionAttributeSource definition.// 建立AnnotationTransactionAttributeSource类型的BeanRootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
// Create the TransactionInterceptor definition.// 建立TransactionInterceptor类型的BeanRootBeanDefinition 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.// 建立BeanFactoryTransactionAttributeSourceAdvisor类型的BeanRootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);// 将上面AnnotationTransactionAttributeSource类型Bean注入进上面的AdvisoradvisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));// 将上面TransactionInterceptor类型Bean注入进上面的AdvisoradvisorDef.getPropertyValues().add("adviceBeanName", interceptorName);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);// 将上面三个Bean注册进IOC中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);}}

这里分别是注册了三个Bean,和一个InfrastructureAdvisorAutoProxyCreator,其中三个Bean支撑了整个事务的功能。ide

咱们首先须要回顾一下AOP的原理,AOP中有一个 Advisor 存放在代理类中,而Advisor中有advise与pointcut信息,每次执行被代理类的方法时都会执行代理类的invoke(若是是JDK代理)方法,而invoke方法会根据advisor中的pointcut动态匹配这个方法须要执行的advise链,遍历执行advise链,从而达到AOP切面编程的目的。函数

  • BeanFactoryTransactionAttributeSourceAdvisor:首先看这个类的继承结构,能够看到这个类实际上是一个Advisor,其实由名字也能看出来,类中有几个关键地方注意一下,在以前的注册过程当中,将两个属性注入进这个Bean中:

  •  
// 将上面AnnotationTransactionAttributeSource类型Bean注入进上面的AdvisoradvisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));// 将上面TransactionInterceptor类型Bean注入进上面的AdvisoradvisorDef.getPropertyValues().add("adviceBeanName", interceptorName);

那么它们被注入成什么了呢?进入BeanFactoryTransactionAttributeSourceAdvisor一看便知。

  •  
@Nullableprivate TransactionAttributeSource transactionAttributeSource;

在其父类中有属性:

  •  
@Nullableprivate String adviceBeanName;

也就是说,这里先将上面的TransactionInterceptor的BeanName传入到Advisor中,而后将AnnotationTransactionAttributeSource这个Bean注入到Advisor中,那么这个Source Bean有什么用呢?能够继续看看BeanFactoryTransactionAttributeSourceAdvisor的源码。

  •  
private final TransactionAttributeSourcePointcut pointcut = new     TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};

看到这里应该明白了,这里的Source是提供了pointcut信息,做为存放事务属性的一个类注入进Advisor中,到这里应该知道注册这三个Bean的做用了吧?首先注册pointcut、advice、advisor,而后将pointcut和advice注入进advisor中,在以后动态代理的时候会使用这个Advisor去寻找每一个Bean是否须要动态代理(取决因而否有开启事务),由于Advisor有pointcut信息。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  • InfrastructureAdvisorAutoProxyCreator:在方法开头,首先就调用了AopNamespeceUtils去注册了这个Bean,那么这个Bean是干什么用的呢?仍是先看看这个类的结构。这个类继承了AbstractAutoProxyCreator,看到这个名字,熟悉AOP的话应该已经知道它是怎么作的了吧?其次这个类还实现了BeanPostProcessor接口,凡事实现了这个BeanPost接口的类,咱们首先关注的就是它的postProcessAfterInitialization方法,这里在其父类也就是刚刚提到的AbstractAutoProxyCreator这里去实现。(这里须要知道Spring容器初始化Bean的过程,关于BeanPostProcessor的使用我会另开一篇讲解。若是不知道只需了解若是一个Bean实现了BeanPostProcessor接口,当全部Bean实例化且依赖注入以后初始化方法以后会执行这个实现Bean的postProcessAfterInitialization方法)

进入这个函数:

  •  
public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext);}
@Nullablepublic static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,@Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);}

对于解析来的代码流程AOP中已经有所分析,上面的两个函数主要目的是注册了InfrastructureAdvisorAutoProxyCreator类型的bean,那么注册这个类的目的是什么呢?查看这个类的层次,以下图所示:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

从上面的层次结构中能够看到,InfrastructureAdvisorAutoProxyCreator间接实现了SmartInstantiationAwareBeanPostProcessor,而SmartInstantiationAwareBeanPostProcessor又继承自InstantiationAwareBeanPostProcessor,也就是说在Spring中,全部bean实例化时Spring都会保证调用其postProcessAfterInstantiation方法,其实现是在父类AbstractAutoProxyCreator类中实现。

以以前的示例为例,当实例化AccountServiceImpl的bean时便会调用此方法,方法以下:

  •  
@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {// 根据给定的bean的class和name构建出key,格式:beanClassName_beanNameObject cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {// 若是它适合被代理,则须要封装指定beanreturn wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}

 这里实现的主要目的是对指定bean进行封装,固然首先要肯定是否须要封装,检测与封装的工做都委托给了wrapIfNecessary函数进行。

  •  
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 若是处理过这个bean的话直接返回if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// 以后若是Bean匹配不成功,会将Bean的cacheKey放入advisedBeans中// value为false,因此这里能够用cacheKey判断此bean是否以前已经代理不成功了if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 这里会将Advise、Pointcut、Advisor类型的类过滤,直接不进行代理,returnif (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {// 这里即为不成功的状况,将false放入Map中this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
// Create proxy if we have advice.// 这里是主要验证的地方,传入Bean的class与beanName去判断此Bean有哪些AdvisorObject[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);// 若是有相应的advisor被找到,则用advisor与此bean作一个动态代理,将这两个的信息// 放入代理类中进行代理if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 建立代理的地方Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());// 返回代理对象return proxy;}// 若是此Bean没有一个Advisor匹配,将返回null也就是DO_NOT_PROXY// 也就是会走到这一步,将其cacheKey,false存入Map中this.advisedBeans.put(cacheKey, Boolean.FALSE);// 不代理直接返回原beanreturn bean;}

wrapIfNecessary函数功能实现起来很复杂,可是逻辑上理解起来仍是相对简单的,在wrapIfNecessary函数中主要的工做以下:

(1)找出指定bean对应的加强器。

(2)根据找出的加强器建立代理。

听起来彷佛简单的逻辑,Spring中又作了哪些复杂的工做呢?对于建立代理的部分,经过以前的分析相信你们已经很熟悉了,可是对于加强器的获取,Spring又是怎么作的呢?

回到顶部

获取对应class/method的加强器

获取指定bean对应的加强器,其中包含两个关键字:加强器与对应。也就是说在 getAdvicesAndAdvisorsForBean函数中,不但要找出加强器,并且还须要判断加强器是否知足要求。

  •  
@Override@Nullableprotected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {List<Advisor> candidateAdvisors = findCandidateAdvisors();List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}

 

寻找候选加强器

  •  
protected List<Advisor> findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");return this.advisorRetrievalHelper.findAdvisorBeans();}
public List<Advisor> findAdvisorBeans() {// Determine list of advisor bean names, if not cached already.String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {// 获取BeanFactory中全部对应Advisor.class的类名// 这里和AspectJ的方式有点不一样,AspectJ是获取全部的Object.class,而后经过反射过滤有注解AspectJ的类advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}if (advisorNames.length == 0) {return new ArrayList<>();}
List<Advisor> advisors = new ArrayList<>();for (String name : advisorNames) {if (isEligibleBean(name)) {if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isDebugEnabled()) {logger.debug("Skipping currently created advisor '" + name + "'");}}else {try {//直接获取advisorNames的实例,封装进advisors数组advisors.add(this.beanFactory.getBean(name, Advisor.class));}catch (BeanCreationException ex) {Throwable rootCause = ex.getMostSpecificCause();if (rootCause instanceof BeanCurrentlyInCreationException) {BeanCreationException bce = (BeanCreationException) rootCause;String bceBeanName = bce.getBeanName();if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {if (logger.isDebugEnabled()) {logger.debug("Skipping advisor '" + name +"' with dependency on currently created bean: " + ex.getMessage());}continue;}}throw ex;}}}}return advisors;}

首先是经过BeanFactoryUtils类提供的工具方法获取全部对应Advisor.class的类,获取办法无非是使用ListableBeanFactory中提供的方法:

  •  
String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
 
 

在咱们讲解自定义标签时曾经注册了一个类型为 BeanFactoryTransactionAttributeSourceAdvisor 的 bean,而在此 bean 中咱们又注入了另外两个Bean,那么此时这个 Bean 就会被开始使用了。由于 BeanFactoryTransactionAttributeSourceAdvisor一样也实现了 Advisor接口,那么在获取全部加强器时天然也会将此bean提取出来, 并随着其余加强器一块儿在后续的步骤中被织入代理。

 

候选加强器中寻找到匹配项

当找出对应的加强器后,接下来的任务就是看这些加强器是否与对应的class匹配了,固然不仅是class,class内部的方法若是匹配也能够经过验证。

  •  
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new ArrayList<>();// 首先处理引介加强for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {// 引介加强已经处理if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}// 对于普通bean的处理if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
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;}}

BeanFactoryTransactionAttributeSourceAdvisor 间接实现了PointcutAdvisor。所以,在canApply函数中的第二个if判断时就会经过判断,会将BeanFactoryTransactionAttributeSourceAdvisor中的getPointcut()方法返回值做为参数继续调用canApply方法,而 getPoint()方法返回的是TransactionAttributeSourcePointcut类型的实例。对于 transactionAttributeSource这个属性你们还有印象吗?这是在解析自定义标签时注入进去的。

  •  
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};

那么,使用TransactionAttributeSourcePointcut类型的实例做为函数参数继续跟踪canApply。

  •  
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;}
// 此时的pc表示TransactionAttributeSourcePointcut// pc.getMethodMatcher()返回的正是自身(this)MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}
Set<Class<?>> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}//获取对应类的全部接口classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));//对类进行遍历for (Class<?> clazz : classes) {//反射获取类中全部的方法Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {//对类和方法进行加强器匹配if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :methodMatcher.matches(method, targetClass)) {return true;}}}
return false;}

经过上面函数大体能够理清大致脉络,首先获取对应类的全部接口并连同类自己一块儿遍历,遍历过程当中又对类中的方法再次遍历,一旦匹配成功便认为这个类适用于当前加强器。

到这里咱们不由会有疑问,对于事物的配置不只仅局限于在函数上配置,咱们都知道,在类或接口上的配置能够延续到类中的每一个函数,那么,若是针对每一个函数迸行检测,在类自己上配罝的事务属性岂不是检测不到了吗?带着这个疑问,咱们继续探求matcher方法。

作匹配的时候 methodMatcher.matches(method, targetClass)会使用 TransactionAttributeSourcePointcut 类的 matches 方法。

  •  
@Overridepublic boolean matches(Method method, Class<?> targetClass) {if (TransactionalProxy.class.isAssignableFrom(targetClass)) {return false;}// 自定义标签解析时注入TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}

此时的 tas 表示 AnnotationTransactionAttributeSource 类型,这里会判断tas.getTransactionAttribute(method, targetClass) != null,而 AnnotationTransactionAttributeSource 类型的 getTransactionAttribute 方法以下:

  •  
@Override@Nullablepublic TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {if (method.getDeclaringClass() == Object.class) {return null;}
Object cacheKey = getCacheKey(method, targetClass);Object cached = this.attributeCache.get(cacheKey);//先从缓存中获取TransactionAttributeif (cached != null) {if (cached == NULL_TRANSACTION_ATTRIBUTE) {return null;}else {return (TransactionAttribute) cached;}}else {// 若是缓存中没有,工做又委托给了computeTransactionAttribute函数TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);// Put it in the cache.if (txAttr == null) {// 设置为空this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);}else {String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);if (txAttr instanceof DefaultTransactionAttribute) {((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);}if (logger.isDebugEnabled()) {logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);}//加入缓存中this.attributeCache.put(cacheKey, txAttr);}return txAttr;}}

尝试从缓存加载,若是对应信息没有被缓存的话,工做又委托给了computeTransactionAttribute函数,在computeTransactionAttribute函数中咱们终于看到了事务标签的提取过程。

 

提取事务标签

  •  
@Nullableprotected 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表明实现类中的方法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;}

对于事务属性的获取规则相信你们都已经很清楚,若是方法中存在事务属性,则使用方法上的属性,不然使用方法所在的类上的属性,若是方法所在类的属性上仍是没有搜寻到对应的事务属性,那么在搜寻接口中的方法,再没有的话,最后尝试搜寻接口的类上面的声明。对于函数computeTransactionAttribute中的逻辑与咱们所认识的规则并没有差別,可是上面函数中并无真正的去作搜寻事务属性的逻辑,而是搭建了个执行框架,将搜寻事务属性的任务委托给了 findTransactionAttribute 方法去执行。

  •  
@Override@Nullableprotected TransactionAttribute findTransactionAttribute(Class<?> clazz) {return determineTransactionAttribute(clazz);}
@Nullableprotected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {for (TransactionAnnotationParser annotationParser : this.annotationParsers) {TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);if (attr != null) {return attr;}}return null;}

this.annotationParsers 是在当前类 AnnotationTransactionAttributeSource 初始化的时候初始化的,其中的值被加入了 SpringTransactionAnnotationParser,也就是当进行属性获取的时候实际上是使用 SpringTransactionAnnotationParser 类的 parseTransactionAnnotation 方法进行解析的。

  •  
@Override@Nullablepublic TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(ae, Transactional.class, false, false);if (attributes != null) {return parseTransactionAnnotation(attributes);}else {return null;}}

至此,咱们终于看到了想看到的获取注解标记的代码。首先会判断当前的类是否含有 Transactional注解,这是事务属性的基础,固然若是有的话会继续调用parseTransactionAnnotation 方法解析详细的属性。

  •  
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");// 解析propagationrbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");// 解析isolationrbta.setIsolationLevel(isolation.value());// 解析timeoutrbta.setTimeout(attributes.getNumber("timeout").intValue());// 解析readOnlyrbta.setReadOnly(attributes.getBoolean("readOnly"));// 解析valuerbta.setQualifier(attributes.getString("value"));ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>();// 解析rollbackForClass<?>[] rbf = attributes.getClassArray("rollbackFor");for (Class<?> rbRule : rbf) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}// 解析rollbackForClassNameString[] rbfc = attributes.getStringArray("rollbackForClassName");for (String rbRule : rbfc) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}// 解析noRollbackForClass<?>[] nrbf = attributes.getClassArray("noRollbackFor");for (Class<?> rbRule : nrbf) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}// 解析noRollbackForClassNameString[] nrbfc = attributes.getStringArray("noRollbackForClassName");for (String rbRule : nrbfc) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}rbta.getRollbackRules().addAll(rollBackRules);return rbta;}

至此,咱们终于完成了事务标签的解析。回顾一下,咱们如今的任务是找出某个加强器是否适合于对应的类,而是否匹配的关键则在因而否从指定的类或类中的方法中找到对应的事务属性,如今,咱们以AccountServiceImpl为例,已经在它的接口AccountServiceImp中找到了事务属性,因此,它是与事务加强器匹配的,也就是它会被事务功能修饰。

至此,事务功能的初始化工做便结束了,当判断某个bean适用于事务加强时,也就是适用于加强器BeanFactoryTransactionAttributeSourceAdvisor

BeanFactoryTransactionAttributeSourceAdvisor 做为 Advisor 的实现类,天然要听从 Advisor 的处理方式,当代理被调用时会调用这个类的加强方法,也就是此bean的Advice,又由于在解析事务定义标签时咱们把Transactionlnterceptor类的bean注人到了 BeanFactoryTransactionAttributeSourceAdvisor中,因此,在调用事务加强器加强的代理类时会首先执行Transactionlnterceptor进行加强,同时,也就是在Transactionlnterceptor类中的invoke方法中完成了整个事务的逻辑。

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相关文章
相关标签/搜索