Spring事务原理?事务在方法间如何传播?为什么会失效?( 二 )

这里的流程比较长 , 但逻辑很简单 。 首先来看注册事务AOP入口类是哪个:
public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {// 将优先级更高的AOP入口类放入到IOC容器中BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));// 设置代理生成的方式以及是否缓存代理类到当前线程useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext); }主要看registerAutoProxyCreatorIfNecessary方法:
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, @Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");// 判断传进来的类和ICO中当前存在的类哪个优先级更高 , 将更高的放入IOC中if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}//把AOP入口类封装成beanDefinition对象 , 要实例化RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//注解aop入口类的beanName名称 AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAMEregistry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition; }首先判断容器中是否已经存在AOP入口类 , 如果不存在则直接创建InfrastructureAdvisorAutoProxyCreator的BeanDefinition对象注册到容器中 , 这个类也是我之前分析的AOP入口类AbstractAutoProxyCreator的子类 , 再来看看其继承关系:
Spring事务原理?事务在方法间如何传播?为什么会失效?文章插图
你会不会疑惑 , 这么多子类 , 到底会使用哪一个呢?回到刚刚的代码中 , 可以看到如果已经存在一个入口类了 , 就会通过findPriorityForClass获取两个类的优先级 , 最终就会使用优先级更大的那个 , 那么它们的优先级顺序是怎样的呢?
private static final List> APC_PRIORITY_LIST = new ArrayList<>(3); static {// Set up the escalation list...APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); } private static int findPriorityForClass(@Nullable String className) {// 索引即是优先级 , 越大优先级越高 , IOC中只会存在一个事务AOP入口类for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {Class clazz = APC_PRIORITY_LIST.get(i);if (clazz.getName().equals(className)) {return i;}}throw new IllegalArgumentException("Class name [" + className + "] is not a known auto-proxy creator class"); }可以看到 , InfrastructureAdvisorAutoProxyCreator是优先级最低的 , 基本上不会起作用;AspectJAwareAdvisorAutoProxyCreator是当我们配置了标签时会注册 , 也就是xml配置的AOP的入口类;而AnnotationAwareAspectJAutoProxyCreator是当我们配置了或使用@EnableAspectJAutoProxy注解时注册 , 因此大部分情况下都是使用的AnnotationAwareAspectJAutoProxyCreator 。 注册完AOP的入口类后 , 回到configureAutoProxyCreator方法:
RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName =parserContext.getReaderContext().registerWithGeneratedName(sourceDef);AnnotationTransactionAttributeSource类的作用就是封装事务注解@Transactional的属性 , 这里需要记住其继承体系以及熟悉该类和其父类的属性和方法 , 对后面分析事物切面执行原理有帮助:
Spring事务原理?事务在方法间如何传播?为什么会失效?文章插图
紧接着就是创建了TransactionInterceptor对象 , 专门的事务拦截器 , 并且该类是MethodInterceptor的子类 , 看到这个应该不陌生了 , 我们知道AOP调用链在执行过程中主要就是调用该类的invoke的方法 , 因此它是事务切面执行的入口 。 既然有了Interceptor , 那么必不可少的还应该有Advisor , 而Advisor又是由Advice和Poincut组成的 , 这样才能构成一个完整的切面 , 所以该方法后面就是创建这两个对象 。 以上就是xml配置AOP注解支持的原理 , 很简单 , 下面再来看看零配置又是如何实现的 。