// org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor@Bean(name =TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)publicBeanFactoryTransactionAttributeSourceAdvisortransactionAdvisor(TransactionAttributeSource transactionAttributeSource,TransactionInterceptor transactionInterceptor){// step into ...// 既然是advisor 里面应该要有 pointcut的匹配方法BeanFactoryTransactionAttributeSourceAdvisor advisor =newBeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);if(this.enableTx !=null){
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));}return advisor;}publicclassBeanFactoryTransactionAttributeSourceAdvisorextendsAbstractBeanFactoryPointcutAdvisor{@NullableprivateTransactionAttributeSource transactionAttributeSource;// step into ...privatefinalTransactionAttributeSourcePointcut pointcut =newTransactionAttributeSourcePointcut(){@Override@NullableprotectedTransactionAttributeSourcegetTransactionAttributeSource(){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
*/publicvoidsetTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource){this.transactionAttributeSource = transactionAttributeSource;}/**
* Set the {@link ClassFilter} to use for this pointcut.
* Default is {@link ClassFilter#TRUE}.
*/publicvoidsetClassFilter(ClassFilter classFilter){this.pointcut.setClassFilter(classFilter);}@OverridepublicPointcutgetPointcut(){returnthis.pointcut;}}
1.1 Pointcut & matches()
@SuppressWarnings("serial")abstractclassTransactionAttributeSourcePointcutextendsStaticMethodMatcherPointcutimplementsSerializable{// 匹配方法@Overridepublicbooleanmatches(Method method,Class<?> targetClass){TransactionAttributeSource tas =getTransactionAttributeSource();return(tas ==null|| tas.getTransactionAttribute(method, targetClass)!=null);}/**
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/@NullableprotectedabstractTransactionAttributeSourcegetTransactionAttributeSource();// 匹配所在的类/**
* {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}
* for filtering classes whose methods are not worth searching to begin with.
*/privateclassTransactionAttributeSourceClassFilterimplementsClassFilter{@Overridepublicbooleanmatches(Class<?> clazz){if(TransactionalProxy.class.isAssignableFrom(clazz)||TransactionManager.class.isAssignableFrom(clazz)||PersistenceExceptionTranslator.class.isAssignableFrom(clazz)){returnfalse;}TransactionAttributeSource tas =getTransactionAttributeSource();// step into ...return(tas ==null|| tas.isCandidateClass(clazz));}}}
2. 解析@Transactional得到TransactionAttribute
// org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute@Override@NullablepublicTransactionAttributegetTransactionAttribute(Method method,@NullableClass<?> targetClass){if(method.getDeclaringClass()==Object.class){returnnull;}// First, see if we have a cached value.Object cacheKey =getCacheKey(method, targetClass);TransactionAttribute 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){returnnull;}else{return cached;}}// 没有命中缓存 -> 第一次加载else{// step into ...// 根据方法、所在类来计算得到transactionAttribute// We need to work it out.TransactionAttribute txAttr =computeTransactionAttribute(method, targetClass);// Put it in the cache.if(txAttr ==null){// 如果获得到的transactionAttribute为Null,则缓存默认的空值this.attributeCache.put(cacheKey,NULL_TRANSACTION_ATTRIBUTE);}else{// 下面一坨都是为了输出日志而已String methodIdentification =ClassUtils.getQualifiedMethodName(method, targetClass);if(txAttr instanceofDefaultTransactionAttribute){((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);}if(logger.isTraceEnabled()){
logger.trace("Adding transactional method '"+ methodIdentification +"' with attribute: "+ txAttr);}this.attributeCache.put(cacheKey, txAttr);}return txAttr;}}// org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method)@Override@NullableprotectedTransactionAttributefindTransactionAttribute(Method method){returndetermineTransactionAttribute(method);}// org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute@NullableprotectedTransactionAttributecomputeTransactionAttribute(Method method,@NullableClass<?> targetClass){// 该方法并不是public的// Don't allow no-public methods as required.if(allowPublicMethodsOnly()&&!Modifier.isPublic(method.getModifiers())){returnnull;}// 获取其接口方法,如果有的话// The method may be on an interface, but we need attributes from the target class.// If the target class is null, the method will be unchanged.Method specificMethod =AopUtils.getMostSpecificMethod(method, targetClass);// step into ...// 获取方法相关的transactionAttribute// 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;}}returnnull;}// org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#determineTransactionAttribute@NullableprotectedTransactionAttributedetermineTransactionAttribute(AnnotatedElement element){for(TransactionAnnotationParser parser :this.annotationParsers){// step into ...TransactionAttribute attr = parser.parseTransactionAnnotation(element);if(attr !=null){return attr;}}returnnull;}// org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)@Override@NullablepublicTransactionAttributeparseTransactionAnnotation(AnnotatedElement element){//查找方法或者类上的@Transactional注解,这里会递归的进行向上查找//如果在当前方法/类上没找到,那么会继续在父类/接口的方法/类上查找,最终将使用找到的第一个注解数据//这就是在接口方法或者接口上的事务注解也能生效的原因,但是它们的优先级更低AnnotationAttributes attributes =AnnotatedElementUtils.findMergedAnnotationAttributes(
element,Transactional.class,false,false);//如果找到了@Transactional注解if(attributes !=null){// step into ...//解析注解属性,封装为一个TransactionAttribute并返回,实际类型为RuleBasedTransactionAttributereturnparseTransactionAnnotation(attributes);}else{returnnull;}}// org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(org.springframework.core.annotation.AnnotationAttributes)protectedTransactionAttributeparseTransactionAnnotation(AnnotationAttributes attributes){RuleBasedTransactionAttribute rbta =newRuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));List<RollbackRuleAttribute> rollbackRules =newArrayList<>();for(Class<?> rbRule : attributes.getClassArray("rollbackFor")){
rollbackRules.add(newRollbackRuleAttribute(rbRule));}for(String rbRule : attributes.getStringArray("rollbackForClassName")){
rollbackRules.add(newRollbackRuleAttribute(rbRule));}for(Class<?> rbRule : attributes.getClassArray("noRollbackFor")){
rollbackRules.add(newNoRollbackRuleAttribute(rbRule));}for(String rbRule : attributes.getStringArray("noRollbackForClassName")){
rollbackRules.add(newNoRollbackRuleAttribute(rbRule));}
rbta.setRollbackRules(rollbackRules);return rbta;}