原文连接:https://www.cnblogs.com/leaveast/p/11765503.html,侵删
1.事物的声明阶段
@EnableTransactionManagement,是我们开启注解事物的第一步,我们来看下这个类为我们干了什么
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement {</span><span style="color: #0000ff;">boolean</span> proxyTargetClass() <span style="color: #0000ff;">default</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">; AdviceMode mode() </span><span style="color: #0000ff;">default</span><span style="color: #000000;"> AdviceMode.PROXY; </span><span style="color: #0000ff;">int</span> order() <span style="color: #0000ff;">default</span><span style="color: #000000;"> Ordered.LOWEST_PRECEDENCE;
}
我们主要看 TransactionManagementConfigurationSelector 干了件什么事情。它主要往spring 容器中导入了 AutoProxyRegistrar , ProxyTransactionManagementConfiguration两个对象。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } }}
ProxyTransactionManagementConfiguration的作用,我们可以看到此类是一个配置类,主要为spring容器中导入了3个bean。这三个bean分别的作用,我们下来详说
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {@Bean(name </span>=<span style="color: #000000;"> TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); advisor.setOrder(</span><span style="color: #0000ff;">this</span>.enableTx.<Integer>getNumber("order"<span style="color: #000000;">)); </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> TransactionAttributeSource transactionAttributeSource() { </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> AnnotationTransactionAttributeSource(); } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span>.txManager != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { interceptor.setTransactionManager(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.txManager); } </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> interceptor; }
}
AutoProxyRegistrar 这个类,实现了ImportBeanDefinitionRegistrar接口,主要是为容器中注入了 InfrastructureAdvisorAutoProxyCreator 这个bean。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Log logger =<span style="color: #000000;"> LogFactory.getLog(getClass());</span><span style="color: #000000;"> @Override </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { </span><span style="color: #0000ff;">boolean</span> candidateFound = <span style="color: #0000ff;">false</span><span style="color: #000000;">; Set</span><String> annoTypes =<span style="color: #000000;"> importingClassMetadata.getAnnotationTypes(); </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (String annoType : annoTypes) { AnnotationAttributes candidate </span>=<span style="color: #000000;"> AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType); </span><span style="color: #0000ff;">if</span> (candidate == <span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">continue</span><span style="color: #000000;">; } Object mode </span>= candidate.get("mode"<span style="color: #000000;">); Object proxyTargetClass </span>= candidate.get("proxyTargetClass"<span style="color: #000000;">); </span><span style="color: #0000ff;">if</span> (mode != <span style="color: #0000ff;">null</span> && proxyTargetClass != <span style="color: #0000ff;">null</span> && AdviceMode.<span style="color: #0000ff;">class</span> == mode.getClass() &&<span style="color: #000000;"> Boolean.</span><span style="color: #0000ff;">class</span> ==<span style="color: #000000;"> proxyTargetClass.getClass()) { candidateFound </span>= <span style="color: #0000ff;">true</span><span style="color: #000000;">; </span><span style="color: #0000ff;">if</span> (mode ==<span style="color: #000000;"> AdviceMode.PROXY) { AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> ((Boolean) proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); </span><span style="color: #0000ff;">return</span><span style="color: #000000;">; } } } }</span><span style="color: #000000;"> }
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
}
我们首先来看一下这个类的继承关系图。
这个类首先是beanpostprocessor的实现类,他会对所有的bean做一次后置增强处理,我们在AbstractAutoProxyCreator中的 postProcessAfterInitialization 方法中可以看到,他会根据规则去对bean包装从而创造满足条件的代理。
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ @Override 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); } } return bean; }
我们接下来进入 wrapIfNecessary 方法
// 如果需要的话,包装给定的bean,也就是说它是否有资格代理。 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(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; }</span><span style="color: #008000;">//</span><span style="color: #008000;"> Create proxy if we have advice.</span> Object[] specificInterceptors = <span style="color: #ff0000;">getAdvicesAndAdvisorsForBean</span>(bean.getClass(), beanName, <span style="color: #0000ff;">null</span><span style="color: #000000;">); </span><span style="color: #0000ff;">if</span> (specificInterceptors !=<span style="color: #000000;"> DO_NOT_PROXY) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy </span>=<span style="color: #000000;"> createProxy( bean.getClass(), beanName, specificInterceptors, </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> SingletonTargetSource(bean)); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.proxyTypes.put(cacheKey, proxy.getClass()); </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> proxy; } </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.advisedBeans.put(cacheKey, Boolean.FALSE); </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> bean; }</span></pre>
我们着重关注一下 getAdvicesAndAdvisorsForBean 方法
@Override protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
这个方法没什么说的,主要表达的意思是为bean找到合格的增强器。
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; }
在 findCandidateAdvisors 方法中,我们可以看到我们上文中注入的三个bean中的其中一个 BeanFactoryTransactionAttributeSourceAdvisor,这个bean可以理解为我们的事物增强器。
public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // 找到上文注入的 BeanFactoryTransactionAttributeSourceAdvisor advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); }return advisors; }
接下来我们看 findAdvisorsThatCanApply 方法,这个方法主要实现了,候选的增强器是否可以对当前bean使用。
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); 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 processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
我们进入方法走到canApply处,继续往下跟。
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; } }
先判断类型后做一次转化,再次进入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; }MethodMatcher methodMatcher </span>=<span style="color: #000000;"> pc.getMethodMatcher(); </span><span style="color: #0000ff;">if</span> (methodMatcher ==<span style="color: #000000;"> MethodMatcher.TRUE) { </span><span style="color: #008000;">//</span><span style="color: #008000;"> No need to iterate the methods if we\'re matching any method anyway...</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">; </span><span style="color: #0000ff;">if</span> (methodMatcher <span style="color: #0000ff;">instanceof</span><span style="color: #000000;"> IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher </span>=<span style="color: #000000;"> (IntroductionAwareMethodMatcher) methodMatcher; } Set</span><Class<?>> classes = <span style="color: #0000ff;">new</span> LinkedHashSet<Class<?>><span style="color: #000000;">(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); </span><span style="color: #0000ff;">for</span> (Class<?><span style="color: #000000;"> clazz : classes) { Method[] methods </span>=<span style="color: #000000;"> ReflectionUtils.getAllDeclaredMethods(clazz); </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (Method method : methods) { </span><span style="color: #0000ff;">if</span> ((introductionAwareMethodMatcher != <span style="color: #0000ff;">null</span> &&<span style="color: #000000;"> introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) </span>||<span style="color: #000000;"><span style="color: #ff0000;"> methodMatcher.matches(method, targetClass)</span>) { </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">; } } } </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">; }</span></pre>
进入matches方法,下来的代码我会合并的连贯一些
@Override public boolean matches(Method method, Class<?> targetClass) { if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) { return false; } TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); }
// 进入AbstractFallbackTransactionAttributeSource.getTransactionAttribute()
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
进入解析的流程
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {@Override </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) { <span style="color: #ff0000;">AnnotationAttributes attributes </span></span><span style="color: #ff0000;">= AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class); </span><span style="color: #0000ff;">if</span> (attributes != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> parseTransactionAnnotation(attributes); } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">; } } </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> TransactionAttribute parseTransactionAnnotation(Transactional ann) { </span><span style="color: #0000ff;">return</span> parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, <span style="color: #0000ff;">false</span>, <span style="color: #0000ff;">false</span><span style="color: #000000;">)); } </span><span style="color: #0000ff;">protected</span><span style="color: #000000;"> TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> RuleBasedTransactionAttribute(); Propagation propagation </span>= attributes.getEnum(<span style="color: #ff0000;">"propagation"</span><span style="color: #000000;">); rbta.setPropagationBehavior(<span style="color: #ff0000;">propagation.value()</span>); Isolation isolation </span>= attributes.getEnum(<span style="color: #ff0000;">"isolation"</span><span style="color: #000000;">); rbta.setIsolationLevel(<span style="color: #ff0000;">isolation.value()</span>); rbta.setTimeout(attributes.getNumber(</span>"timeout"<span style="color: #000000;">).intValue()); rbta.setReadOnly(attributes.getBoolean(</span>"readOnly"<span style="color: #000000;">)); rbta.setQualifier(attributes.getString(</span>"value"<span style="color: #000000;">)); ArrayList</span><RollbackRuleAttribute> rollBackRules = <span style="color: #0000ff;">new</span> ArrayList<RollbackRuleAttribute><span style="color: #000000;">(); Class</span><?>[] rbf = attributes.getClassArray("rollbackFor"<span style="color: #000000;">); </span><span style="color: #0000ff;">for</span> (Class<?><span style="color: #000000;"> rbRule : rbf) { RollbackRuleAttribute rule </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] rbfc </span>= attributes.getStringArray("rollbackForClassName"<span style="color: #000000;">); </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (String rbRule : rbfc) { RollbackRuleAttribute rule </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } Class</span><?>[] nrbf = attributes.getClassArray("noRollbackFor"<span style="color: #000000;">); </span><span style="color: #0000ff;">for</span> (Class<?><span style="color: #000000;"> rbRule : nrbf) { NoRollbackRuleAttribute rule </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] nrbfc </span>= attributes.getStringArray("noRollbackForClassName"<span style="color: #000000;">); </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (String rbRule : nrbfc) { NoRollbackRuleAttribute rule </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } rbta.getRollbackRules().addAll(rollBackRules); </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> rbta; }</span><span style="color: #000000;">
}
此方法会先拿到标记为 Transcantional 注解的方法,然后遍历属性。最后返回attr,如果解析到的attr不为空,则会将此增强器对待增强的bean做增强处理。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(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; }</span><span style="color: #008000;">//</span><span style="color: #008000;"> Create proxy if we have advice.</span> <span style="color: #ff0000;"> Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 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; } </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.advisedBeans.put(cacheKey, Boolean.FALSE); </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> bean; }</span></pre>
我们回到 wrapIfNecessary方法,如果返回的advisor不为空,我们会为他生成代理对象。
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
这里就跟我们的使用AOP创建代理无缝融合,在找到当前bean确定要进行增强处理和增强的advisor后,使用动态代理的方式创建代理对象。