SpringTransactional源码分析(一)

1.Spring Transactional源码分析

1.核心类

Spring的事务依赖于一个核心的接口PlatformTransactionManager

TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
复制代码

这个接口提供了三个方法,这三个方法见名知意,就是获取事务(开始事务)、提交、回滚。

image-20200623152542467

这个类图展示了它的部分常用的子类,不同的TransactionManager用于不同的框架,比如DataSourceTransactionManager用于JDBCMyBatisJpaTransactionManager用于JPA

还有两个重要的类:TransactionDefinitionTransactionStatus

TransactionDefinition是事务的定义,包含了事务中常用的属性,比如传播行为、隔离级别、超时时间等。

image-20200703142240893

image-20200703142240893

TransactionAttribute继承了TransactionDefinition,主要增加了一个指定异常回滚方法,只配合AOP使用。

TransactionStatus保存了事务的状态,事务的所有操作都是基于这个状态。

image-20200703142603906

image-20200623154650439

image-20200623154709527

SavepointManager就是包含了操作savepoint的三个方法,TransactionStatus实现了SavepointManager,再加上本身提供的一些方法,基本包含了事务的所有状态。后续无论是事务的创建、回滚、完成等都是基于该接口。

SavepointManager还有另外一个重要的子类,JdbcTransactionObjectSupport抽象类,这个类有很多实现类,并且这些实现类都是各个PlatformManager实现类的内部类,用于保存了JDBC连接、事务隔离级别以及保存点的回滚。

2.注册BeanDefintion

org.springframework.transaction.config.TxNamespaceHandler

public class TxNamespaceHandler extends NamespaceHandlerSupport {
   @Override
	public void init() {
		//基于XML
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		//基于注解
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}
}
复制代码

对于每种标签提供了相应的BeanDefinitionParser

1.基于XML配置

image-20200706143954762

TxAdviceBeanDefinitionParser用于解析<tx:advice/>标签。

案例:

<aop:config>
    <aop:pointcut id="pointcut" expression="execution(* com.ly.transactional..*(..))"/>
    <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="pointcut"/>
</aop:config>
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRES_NEW" isolation="READ_COMMITTED"/>
        <tx:method name="get*" propagation="REQUIRED" isolation="DEFAULT"/>
    </tx:attributes>
</tx:advice>
复制代码

事务的基于XML配置的方式是需要<aop:advisor/>标签进行配合使用的,这里主要看事务标签解析。

<aop:config/>会被解析ClassAspectJAwareAdvisorAutoProxyCreatorBeanDefintion,在创建代理类的时候会用到;<aop:pointcut/>会被解析为ClassAspectJExpressionPointcutBeanDefinition<tx:advice/>会被解析为ClassTransactionInterceptorBeanDefintion<aop:advisor/>会被解析为ClassDefaultBeanFactoryPointcutAdvisor,这个Advisor保存了AspectJAwareExpressionPointcutTransactionInterceporRuntimeBeanNameReference,这个Advisor就是后面执行的时候用的。

org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse

@Override
public final BeanDefinition parse(Element element, ParserContext parserContext) {
    AbstractBeanDefinition definition = parseInternal(element, parserContext);
    return definition;
}
复制代码

org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal

@Override
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
    //委派给TxAdviceBeanDefinitionParser
    Class<?> beanClass = getBeanClass(element);
    if (beanClass != null) {
        builder.getRawBeanDefinition().setBeanClass(beanClass);
    }
    //委派给TxAdviceBeanDefinitionParser
    doParse(element, parserContext, builder);
    return builder.getBeanDefinition();
}
复制代码

这里使用了委派模式,将顶层标签的解析和顶层标签的字标签的解析都交由子类去实现。

org.springframework.transaction.config.TxAdviceBeanDefinitionParser#getBeanClass

@Override
protected Class<?> getBeanClass(Element element) {
    return TransactionInterceptor.class;
}
复制代码

这里解析<tx:advice/>标签ClassTransactionInterceptorBeanDefinition

org.springframework.transaction.config.TxAdviceBeanDefinitionParser#doParse

@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
    //1.判断标签是否申明了transaction-manager标签,如果没有申明,则默认查找id为transactionManager的bean作为事务管理器
    builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));

    //2.解析<tx:attributes/>标签,正常情况下,<tx:advice/>标签内只能<=1个该标签
    List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
    if (txAttributes.size() > 1) {
        parserContext.getReaderContext().error(
            "Element <attributes> is allowed at most once inside element <advice>", element);
    }
    else if (txAttributes.size() == 1) {
        // Using attributes source.
        Element attributeSourceElement = txAttributes.get(0);
        //3.创建了Class为NameMatchTransactionAttributeSource的BeanDefinition
        RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
        builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
    }
    else {
        // 假设使用了注解
        builder.addPropertyValue("transactionAttributeSource",
                                 new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
    }
}
复制代码

doParse方法主要做了两件事,第一件事是获取IOC容器中管理的事务管理器(TransactionManager),第二件事是解析<tx:advice/>中的<tx:attributes/>标签,判断是否合法以及该使用何种方法去解析其内部的<tx:method/>标签。

org.springframework.transaction.config.TxAdviceBeanDefinitionParser#parseAttributeSource

/**
* 解析<tx:method/>标签
*/
private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
    //1.解析<tx:method/>标签,该标签在<tx:attributes/>内部中可以有多个
    List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
    ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
        new ManagedMap<TypedStringValue, RuleBasedTransactionAttribute>(methods.size());
    transactionAttributeMap.setSource(parserContext.extractSource(attrEle));

    //2.遍历,获取标签申明的属性,这些属性都是事务执行的支持的属性,和@Transactional注解中支持的属性基本一致
    //这里使用了一个Map,key为name,value为RuleBasedTransactionAttribute,该类是TransactionBeanDefinition的子类,保存了Transaction的基本属性
    for (Element methodEle : methods) {
        String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
        TypedStringValue nameHolder = new TypedStringValue(name);
        nameHolder.setSource(parserContext.extractSource(methodEle));

        RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
        String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
        String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
        String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
        String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
        if (StringUtils.hasText(propagation)) {
            attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation);
        }
        if (StringUtils.hasText(isolation)) {
            attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation);
        }
        if (StringUtils.hasText(timeout)) {
            try {
                attribute.setTimeout(Integer.parseInt(timeout));
            }
            catch (NumberFormatException ex) {
                parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle);
            }
        }
        if (StringUtils.hasText(readOnly)) {
            attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE)));
        }

        List<RollbackRuleAttribute> rollbackRules = new LinkedList<RollbackRuleAttribute>();
        if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) {
            String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
            addRollbackRuleAttributesTo(rollbackRules,rollbackForValue);
        }
        if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
            String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
            addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue);
        }
        attribute.setRollbackRules(rollbackRules);

        transactionAttributeMap.put(nameHolder, attribute);
    }

    //3.最终使用了一个Class为NameMatchTransactionAttributeSource的BeanDefinition,保存这些源信息
    //使用的时候可以通过方法名获取事务信息
    RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
    attributeSourceDefinition.setSource(parserContext.extractSource(attrEle));
    attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
    return attributeSourceDefinition;
}
复制代码

该方法是用来解析<tx:method/>标签的实现,核心流程也很简单,就是申明了MapkeynamevalueRuleBasedTransactionAttribute,该类存储了事务的属性定义,最终申明了一个ClassNameMatchTransactionAttributeSourceBeanDefinition,将上述的map作为属性。

image-20200706171309833

image-20200706153751402

这里使用到了两个类:RuleBasedTransactionAttributeNameMatchTransactionAttributeSource

image-20200706151216692

RuleBasedTransactionAttributeTransactionDefinition的实现,用于保存事务的属性定义,方便执行事务的时候获取。

image-20200706170229172

NameMatchTransactionAttributeSourceTransactionAttributeSource的子类,TransactionAttributeSource只提供了一个方法:

TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass);
复制代码

根据方法获取事物的属性(TransactionAttribute)。

那么TransactionAttributeSource这个接口的作用也显而易见了,用于保存标签解析的时候的事务属性,在执行事物的时候,通过方法名从该接口中获取解析的时候保存的事务属性,具体是从之前的nameMap中获取,以便事务的执行。

2.基于注解

image-20200706154107332

AnnotationDrivenBeanDefinitionParser用于解析<tx:annotation-driven/>标签。

案例:

<tx:annotation-driven transaction-manager="transactionManager"/>
复制代码

org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    //1.注册事务监听器工厂
    registerTransactionalEventListenerFactory(parserContext);
    String mode = element.getAttribute("mode");
    //2.aspectj
    if ("aspectj".equals(mode)) {
        // mode="aspectj"
        registerTransactionAspect(element, parserContext);
    }
    //3.aop
    else {
        // mode="proxy"
        AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    }
    return null;
}
复制代码

基于注解的方式实现主要有两种方式,第一种是基于AspectJ,另一种是基于AOP的,可以通过指定mode属性决定,默认情况都是基于AOP的。

org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator

/**
* 一个内部类依赖AOP实现的时候使用
*/
private static class AopAutoProxyConfigurer {

    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {

        //1.注入class为InfrastructureAdvisorAutoProxyCreator的BeanDefinition,处理了proxy-target-class
        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

        String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
        if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
            Object eleSource = parserContext.extractSource(element);


            //2.创建一个class为AnnotationTransactionAttributeSource的BeanDefinition,用来保存@Transactional注解的内容
            RootBeanDefinition sourceDef = new RootBeanDefinition(
                "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
            sourceDef.setSource(eleSource);
            sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);


            //3.创建一个class为TransactionInterceptor的BeanDefinition,这和Aop是一样的,任何通知最终都是转为Interceptor
            RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
            interceptorDef.setSource(eleSource);
            interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            //4.注册TransactionManager的名称,如果没有指定,默认是transactionManager
            registerTransactionManager(element, interceptorDef);
            interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);


            //5.创建一个class为BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition,保存了上述两个BeanDefinition
            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);
            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);
        }
    }
}
复制代码

首先把<tx:annotation-driven/>标签解析ClassInfrastructureAdvisorAutoProxyCreatorBeanDefinition,后续创建代理的时候使用这个;然后创建了一个ClassAnnotationTransactionAttributeSourceBeanDefintiion,这个类和NameMatchTransactionAttributeSource功能是一样的,只不过一个服务于注解,一个服务于XML;然后创建了一个ClassTransasactionInterceptorBeanDefinition,这和基于注解的是一样的,并且注册IOC容器管理的TransasctionManager;最后创建了一个ClassBeanFactoryTransactionAttributeSourceAdvisorBeanDefinition,这个BeanDefinition将上述的TransactionAttributeSourceTransactionInterceptor的作为属性,后面进行拦截的时候就会使用这个Advisor

image-20200706163843563

image-20200706162738338

两种事务定义的方式使用了不同的自动创建方式,InfrastructureAdvisorAutoProxyCreator只服务于Spring内部的基础设施类。AspectJAwareAdvisorAutoProxyCreator定义了Advisor扩展以及同一切面的不同建议的执行顺序。

image-20200706170209336

AnnotationTransactionAttributeSource继承了AbstractFallbackTransactionAttributeSourceAbstractFallbackTransactionAttributeSource实现了TransactionAttributeSourceAbstractFallbackTransactionAttributeSource中有一个Map用于缓存TransactionAttribute

private final Map<Object, TransactionAttribute> attributeCache =
    new ConcurrentHashMap<Object, TransactionAttribute>(1024);
复制代码

这个attributeCachekeyMethodClassKey,当从AnnotationTransactionAttributeSource中获取TransactionAttribute的时候,就是从这个缓存中获取。在NameMatchTransactionAttributeSource也有一个相似的缓存,只不过key为方法名。

image-20200706170513482

TransactionInterceptorAOP的五种通知的Interceptor是一样的,都是MethodInterceptor的子类,实现了invoke方法,执行事务拦截的时候会执行。

3.创建代理

上面解析BeanDefinition的时候,已经知道了基于XML的时候使用的是AspectJAwareAdvisorAutoProxyCreator,而基于注解的使用的是InfrastructureAdvisorAutoProxyCreator,这两个类都是AbstractAutoProxyCreator的子类,事务创建代理的入口,也就是在这个类中。

1.postProcessBeforeInstantiation

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);

    //1.不需要创建代理
    if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        //2.如果是基础设施或者应该跳过的类,则说明这个类不需要创建代理,缓存起来
        //默认shouldSkip是false,都不应该跳过
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    //2.对于自定义的TargetSource会立即创建代理,并缓存
    if (beanName != null) {
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        //如果不是TargetSource,一般不会走到这里
        if (targetSource != null) {
            this.targetSourcedBeans.add(beanName);
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    }

    return null;
}
复制代码

这个方法实现了InstantiationAwareBeanPostProcessor的方法,用于在Bean实例化之前做处理。这里的是为了判断某个Bean是否需要创建代理,如果Bean是基础设施类(AdvisorAdvicePointcutAopInfrastructureBean)或者应该跳过,则这些Bean不需要被创建代理。

注解:

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    return false;
}
复制代码

XML

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    //1.获取容器中所有的Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        //对于<aop:aspect/>是AspectJPointcutAdvisor
        if (advisor instanceof AspectJPointcutAdvisor) {
            if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                return true;
            }
        }
    }
    return super.shouldSkip(beanClass, beanName);
}
复制代码

是否应该跳过,在AbstractAutoProxyCreator中默认都是falseInfrastructureAdvisorAutoProxyCreator没有重写整个方法;AspectJAwareAdvisorAutoProxyCreator重写了该方法,会判断切面是否是当前的Bean,如果是,则应该跳过,但是由于<aop:advisor/>使用的是DefaultBeanFactoryPointcutAdvisor,所以这里正常情况下也是返回false,这里还调用了一个findCandidateAdvisors方法,这个方法用于获取容器管理的Advisor,然后进行缓存,相对于注解的方式来说Advisor实例化的时间要提前了一点。

org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans

public List<Advisor> findAdvisorBeans() {
    //1.缓存的通知器的名称
    String[] advisorNames = this.cachedAdvisorBeanNames;
    //2.如果cachedAdvisorBeanNames为空,则到容器中查找
    //并设置缓存,后续直接使用缓存即可
    if (advisorNames == null) {
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<Advisor>();
    }
    List<Advisor> advisors = new ArrayList<Advisor>();
    //3.遍历所有的通知器名称
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            //4.忽略正在创建的advisor
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                //5.从容器中获取Advisor,并添加到advisors中,在这个时候Advisor就被实例化了
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
        }
    }
    return advisors;
}
复制代码

最后,对于不需要代理的Bean进行缓存,以便在后面创建代理的时候用作判断,这里只放了核心代码。

2.postProcessAfterInitialization

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    //如果需要,为bean生成代理对象
    return wrapIfNecessary(bean, beanName, cacheKey);
}
复制代码

这个方法实现了BeanPostProcessor的方法,这里只放了核心代码,在Bean初始化方法之后执行,这里的作用就是为Bean创建代理。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //1.直接使用上面的缓存判断
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    //2.这里再判断一次,方式和之前是一样的,防止之前缓存中没有
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    //3.为目标Bean查找合适的通知和通知器
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    //4.如果通知存在,则生成代理
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        //5.创建代理
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    //6.通知不存在,直接返回bean
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}
复制代码

逻辑也很简单,首先判断这个Bean是否之前已经被缓存了应该跳过或者重新使用之前的判断方式再判断一遍,确保当前的Bean是需要创建代理的;然后就是为目标Bean获取符合该Bean可用的Advisor;最后创建代理。

获取候选Advisor

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //1.查找所有的通知器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //2.筛选可以在该bean上应用的通知器,通过ClassFilter和MethodMatcher对目标类和方法进行匹配
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    //3.扩展操作
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
复制代码

首先查找所有的通知器,这里对于XML形式的由于之前shouldSkip的时候已经实例化了Advisor,所以直接可以从缓存中获取实例,而对于注解的方式,就需要现在实例化容器中所有的Advisor,拿到其实例;然后判断获取到的Advisor哪些适用于当前Bean,这里会使用到PointcutClassFilterMethodMatch;最后是扩展Advisor,对于XML会在列表头部加入一个ExposetInvocationInterceptor,使用线程单例记录当前执行的MethodInvocation,对于注解形式不会进行扩展。

匹配当前BeanAdvisor

org.springframework.aop.support.AopUtils#canApply

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
        //1.从通知器中获取ClassFilter,并调用matches进行匹配
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    else if (advisor instanceof PointcutAdvisor) {
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        //2.对于普通Advisor,这里继续调用重载方法进行筛选
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        // It doesn't have a pointcut so we assume it applies.
        return true;
    }
}
复制代码

无论是DefaultBeanFactoryPointcutAdvisor还是BeanFactoryTransactionAttributeSourceAdvisor都是PointcutAdvisor,这里会拿Pointcut去匹配。

XML

org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#getPointcut

public class DefaultBeanFactoryPointcutAdvisor extends AbstractBeanFactoryPointcutAdvisor {
    private Pointcut pointcut = Pointcut.TRUE;
    
	public void setPointcut(Pointcut pointcut) {
		this.pointcut = (pointcut != null ? pointcut : Pointcut.TRUE);
	}

    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }
}
复制代码

虽然该类默认是Pointcut.TRUE,但是这里拿到的是AspectJExpressionPointcut,因为该Advisor使用的是AspectJExpressionPointcut,默认值被覆盖了,后面匹配就会使用AspectJExpressionPointcutClassFilterMethodMatcher

注解:

org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
        @Override
        protected TransactionAttributeSource getTransactionAttributeSource() {
            return transactionAttributeSource;
        }
    };

    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }
}
复制代码

对于DeafultBeanFactoryPointcutAdvisor在这一步只是简单的进行匹配,具体的匹配过程比较复杂;BeanFactoryTransactionAttributeSourceAdvisor使用的是TransactionAttributeSourcePointcut去匹配,TransactionAttributeSourcePointcut使用了ClassFilter.TRUE,也就是说只用方法匹配,类匹配始终都会成功。

org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#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);
}

/**
* 交给子类去实现
*/
protected abstract TransactionAttributeSource getTransactionAttributeSource();
复制代码

image-20200707105948959

BeanFactoryTransactionAttributeSourceAdvisor通过匿名内部类的方式重写了getTransactionAttributeSource方法。

org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute

@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
    if (method.getDeclaringClass() == Object.class) {
        return null;
    }

    //1.从缓存中获取,开始肯定为NULL
    Object cacheKey = getCacheKey(method, targetClass);
    TransactionAttribute cached = this.attributeCache.get(cacheKey);
    if (cached != null) {
        if (cached == NULL_TRANSACTION_ATTRIBUTE) {
            return null;
        }
        else {
            return cached;
        }
    }
    else {
        //2.获取@Transactional的属性值,并放入缓存
        TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        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;
    }
}
复制代码

这个方法就是用来获取@Transactional注解的属性值,并放入缓存,后面执行事务的时候可以直接获取属性值来决定事物的执行。

org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute

protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
    //1.不允许非公共方法
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }

    //2.获取真正的目标类
    Class<?> userClass = ClassUtils.getUserClass(targetClass);
    //3.给定的方法如果在接口中,并且目标类在通过反射调用,则获取目标类的方法,否则方法不变
    Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
    //4.如果要处理泛型参数,则需要找到原始方法
    specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

    //5.尝试在目标方法上查找@Transactional注解
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
        return txAttr;
    }

    //6.目标方法上没找到,则去目标类查找
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
        return txAttr;
    }

    //7.如果传入的方法不等于指定的方法,上面都没获取到,则回滚到原始方法获取
    if (specificMethod != method) {
        txAttr = findTransactionAttribute(method);
        if (txAttr != null) {
            return txAttr;
        }
        txAttr = findTransactionAttribute(method.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }
    }

    return null;
}
复制代码

首先根据传入的方法找到真正的目标方法,比如传入的方法在接口中,则需要找到正在调用的接口的实现类重写的方法;然后先从方法中获取@Transactional注解的属性值,如果方法中没有,则在方法对应的类上获取@Transactional注解的属性值;如果都没有获取到,并传入的方法不等于获取的目标方法,则使用传入的方法在方法上获取@Transactional注解的属性值,如果没有获取到,则从传入的方法的类中获取@Transactional注解的属性值;最终都没有,则返回null

org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#findTransactionAttribute

Override
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
    return determineTransactionAttribute(clazz);
}

@Override
protected TransactionAttribute findTransactionAttribute(Method method) {
    return determineTransactionAttribute(method);
}
复制代码

这里申明了两个重载方法,分别对应根据类和根据方法获取。最终都是调用一个核心方法determineTransactionAttribute

org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#determineTransactionAttribute

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
    if (element.getAnnotations().length > 0) {
        //TransactionAnnotationParser一般都是SpringTransactionAnnotationParser
        for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
            TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
            if (attr != null) {
                return attr;
            }
        }
    }
    return null;
}
复制代码

遍历所有的事务注解解析器,如果有其中一个能解析成功,则说明拿到了当前事务的事务属性值,直接返回即可。这里的TransactionAnnotationParser一般都是SpringTransactionAnnotationParser

org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation

@Override
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
    //这个AnnotationAttributes本质上就是个LinkedHashMap,添加了注解相关的几个属性,以及根据key方便获取枚举的方法
	//这里面比较复杂,知道把@Transactional注解属性值解析成了一个Map就成
    AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
        element, Transactional.class);
    if (attributes != null) {
        return parseTransactionAnnotation(attributes);
    }
    else {
        return null;
    }
}
复制代码

org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation

protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
		RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();

		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 = new ArrayList<RollbackRuleAttribute>();
		for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		rbta.setRollbackRules(rollbackRules);

		return rbta;
	}
复制代码

可以看到最终也是RuleBasedTransactionAttribute,这和基于XML是一样的,拿到值之后,一路返回,进行缓存,方便执行事务的获取,也说明了当前Advisor和目标方法匹配成功。

3. 创建代理

拿到了适合当前BeanAdvisor,接下来就是创建代理了,这里基于XML和注解的都是一模一样的了,当然和AOP创建代理的方式也是一模一样的。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

protected Object createProxy(
    Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    //1.默认情况下,proxy-target-class=false,使用jdk动态代理
    if (!proxyFactory.isProxyTargetClass()) {
        //判断proxy-target-class属性
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            //2.检查目标类是否实现了接口,如没有,则设置proxy-target-class=true,使用cglib动态代理
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    //3.将specificInterceptors中含有的Advice转为Advisor
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    //4.创建代理
    return proxyFactory.getProxy(getProxyClassLoader());
}
复制代码

使用了一个代理工厂ProxyFactory去创建代理对象,设置了如targetSourceAdvisorproxyTargetClass等属性,为后面的创建代理做准备。

判断使用何种代理方式:

org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    //1.是否需要优化||代理类型(前面已经设置过了)||是否实现了接口
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                                         "Either an interface or a target is required for proxy creation.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        //2.使用cglib动态代理
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        //3.使用jdk动态代理
        return new JdkDynamicAopProxy(config);
    }
}
复制代码

这里会判断使用何种方式去创建代理,在Java中主要有两种创建代理的的方式:1.JDK;2.CGLIB。默认情况下使用JDK方式,当然如果目标Bean没有实现接口,则会使用CGLIB,也可通过设置proxy-target-class属性决定使用何种代理方式。

JDK

@Override
public Object getProxy(ClassLoader classLoader) {
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
复制代码

CGLIB

@Override
public Object getProxy(ClassLoader classLoader) {
    //1.从TargetSource获取target的class
    Class<?> rootClass = this.advised.getTargetClass();
    Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

    //2.判断是否已经是代理类了
    Class<?> proxySuperClass = rootClass;
    if (ClassUtils.isCglibProxyClass(rootClass)) {
        proxySuperClass = rootClass.getSuperclass();
        Class<?>[] additionalInterfaces = rootClass.getInterfaces();
        for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
        }
    }
    validateClassIfNecessary(proxySuperClass, classLoader);

    //3.CGLIB
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
        if (classLoader instanceof SmartClassLoader &&
            ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
        }
    }
    enhancer.setSuperclass(proxySuperClass);
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

    //4.各种回调
    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
    }
    //5.回调过滤
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);
    //6.创建代理实例
    return createProxyClassAndInstance(enhancer, callbacks);
}
复制代码

这两种方式基本上都是标准的实现。

image-20200707143550538

代理Bean创建完成并返回,后续执行都是通过代理Bean来实现的。