spring事务如何获取事务增强器

声明

  • 本文章是对标有配置的项目进行获取事务增强器分析。
  • 需要知道spring事务后续流程可以阅读spring事务

原理篇 spring事务获取事务增强器总流程分析

  • 先注册 三个bean, 其中第一个bean会把第二,第三个bean加进去。
  • 在第一步的流程中还会注册InfrastructureAdvisorAutoProxyCreator,这个类是 ,Spring自动调用所有实现了 BeanPostProcessor 接口的 bean 的 方法,这个方法在父类AbstractAutoProxyCreator实现,这个方法是初始化bean的时候,spring会把把所有增强器拿出来,然后查找所有符合bean条件的增强器。
  • 对于@Transaction标注的方法而言,是合适的增强器,根据增强强的规则被@Transaction标注的方法,这也就是为什么service简单自调用事务不起作用原因。

前置知识点篇

  • 织入(weaving): 把切面应用到目标对象来创建新的代理对象的过程。
  • 目标(target): 引入中所提到的,也就是要被通知的对象,也就是真正的业务逻辑.
  • 切面(Aspect): 切面是通知和切入点的结合。
  • 通知(Advice) : before,after,around等
  • 连接点(JoinPoint): (就是spring允许你使用通知的地方,那可真就多了,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点)
  • 切入点(Pointcut ): 上面说的连接点的基础上,来定义切入点
  • 引入(introduction): 把切面(也就是新方法属性:通知定义的)

源码篇

分析原理篇的第一点,以及第二点的注册InfrastructureAdvisorAutoProxyCreator这几个bean
  • 首先tx这个命名空间对应的命名空间处理器是 TxNamespaceHandle,当然也可以全局查找annotation-driven
public void init() {
        registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
        //重点分析对象
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
    }
  • 接下来看AnnotationDrivenBeanDefinitionParser的parse方法
public void init() {
        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.configureAutoProxyCreator(element, parserContext);
        }
        return null;
    }
    }
  • 三个重点bean以及InfrastructureAdvisorAutoProxyCreator的bean被注册
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
    //这里配置org.springframework.aop.config.internalAutoProxyCreator这个bean的exposeProxy属性为true,这个bean用来创建代理的 对应 xml里面 tx: proxy-target-class="true" 属性设置  
    //(如果配置了, 这个bean类型就是AnnotationAwareAspectJAutoProxyCreator)
    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.
        //AnnotationTransactionAttributeSource 主要是用来解析注解属性 继承自AbstractFallbackTransactionAttributeSource
        //主要作用就是解析方法注解, 将事物属性封装成对象缓存起来, 然后如果方法上没注解就去类上或者接口上找~~~
        RootBeanDefinition 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 一看名字就知道是拦截方法的, 通过拦截方法的调用, 处理事务
        RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
        interceptorDef.setSource(eleSource);
        interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registerTransactionManager(element, interceptorDef);//这里通过bean name关联事务管理器
        interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
        String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

        // Create the TransactionAttributeSourceAdvisor definition.
        //BeanFactoryTransactionAttributeSourceAdvisor 事务AOP配置 Pointcut:TransactionAttributeSourcePointcut, advice: TransactionInterceptor 
        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);//关联TransactionInterceptor
        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);
    }
}
分析原理篇的第二点bean初始化时调用的
  • postProcessAfterInitialization分析
//bean初始化成功, 参数, bean:bean实例 beanName:bean在Spring容器中的名字
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        //如果之前调用过getEarlyBeanReference获取包装目标对象到AOP代理对象(如果需要),则不再执行  
        //getEarlyBeanReference 也是创建代理对象, 主要是通过代理来解决循环引用问题
        if (!this.earlyProxyReferences.containsKey(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);//创建代理对象
        }
    }
    return bean;
}
  • 这里的wrapIfNecessary方法, 继续分析
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // Create proxy if we have advice. //注释说的很明白了,如果偶们有advice就创建代理
    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;
    }
}
  • 这里的方法是重点要分析的
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
        List advisors = this.findEligibleAdvisors(beanClass, beanName);
        return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
    }

protected List findEligibleAdvisors(Class beanClass, String beanName) {
        List candidateAdvisors = this.findCandidateAdvisors();
        List eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        this.extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
        }

        return eligibleAdvisors;
    }
  • 可以看到很清晰的逻辑findCandidateAdvisors()找到所有的候选增强器,然后找到所有合适的findAdvisorsThatCanApply()增强器,
  • 找到合适的增强器方法是通过TransactionAttributeSourcePointcut.getClassFilter().matches(targetClass)和getMethodMatcher().matches(method, targetClass)来过滤掉不符合的advisor
  • 最后调用AbstractAutoProxyCreator.createProxy()方法创建代理

参考文章

Spring事务源码梳理1----事务配置解析及切面织入
Spring AOP 术语解释

你可能感兴趣的:(spring事务如何获取事务增强器)