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

基于注解, 首先,我们会在配置文件中使用如下的配置来开启Spring事务注解配置.

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />


当Spring解析配置文件的这一行时,发现元素的命名空间不是 http://www.springframework.org/schema/beans 则会

调用 BeanDefinitionParserDelegate.parseCustomElement() 方法来解析, 该方法的内部又是调用的下面方法来处理的

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
	String namespaceUri = getNamespaceURI(ele);//获取元素命名空间
	NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);//查找相应的命名空间处理器
	if (handler == null) {
		error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
		return null;
	}
	return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));//调用处理器来处理元素, 内部会从map中获取对应的bean处理器来处理, 见后面说明
}


在这里可以看到,是通过 this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 来获取对应的处理器, 具体代码继续跟踪

最后是调用DefaultNamespaceHandlerResolver.resolve(namespaceUri)方法来实现的, 

该方法内部通过查找classpath下面的/META-INF/spring.handlers属性文件来找到命名空间和处理器的对应关系, 

比如说在spring-tx的jar包中,可以看到/META-INF/spring.handlers的内容为

http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler


于是, 我们知道了, tx这个命名空间对应的命名空间处理器是 TxNamespaceHandler 我们来看它的代码

public class TxNamespaceHandler extends NamespaceHandlerSupport {

	static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";

	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";

	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}

	public void init() {
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}

}


代码很简单 NamespaceHandlerResolver 找到处理器后, 会反射创建实例, 然后调用init方法, 我们继续看看 registerBeanDefinitionParser做了什么处理

这个方法主要是将bean定义处理器加入到一个map中, 然后在 parse 方法中, 会根据名字去找到对应的bean定义处理器, 然后调用 处理器的parse方法

public BeanDefinition parse(Element element, ParserContext parserContext) {
        //findParserForElement 在map中找到对应的bean定义处理器, 然后调用 parse
	return findParserForElement(element, parserContext).parse(element, parserContext);
}


这里 TxNamespaceHandler 注册了三个bean定义处理器 分别是 TxAdviceBeanDefinitionParser AnnotationDrivenBeanDefinitionParser JtaTransactionManagerBeanDefinitionParser

分别对应于 tx:advice    tx:annotation-driven    tx:jta-transaction-manager   这里我们用的注解, 所以来看看 AnnotationDrivenBeanDefinitionParser.parse() 做了啥. 具体代码如下

public BeanDefinition parse(Element element, ParserContext parserContext) {
	String mode = element.getAttribute("mode");
	if ("aspectj".equals(mode)) {
		registerTransactionAspect(element, parserContext);// mode="aspectj"
	} else {
	        //对应配置文件中mode属性, 默认值proxy
		AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext); // mode="proxy"
	}
	return null;
}


可以看到, 具体的逻辑在 AopAutoProxyConfigurer.configureAutoProxyCreator() 中, 通过名字可以看出, 和AOP有关, 代码如下

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
    //这里配置org.springframework.aop.config.internalAutoProxyCreator这个bean的exposeProxy属性为true,这个bean用来创建代理的 对应 xml里面 tx: proxy-target-class="true" 属性设置  
    //(如果配置了<aop:aspectj-autoproxy 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);
    }
}

在这个方法中, 想Spring容器注册了三个bean定义:

一个是 AnnotationTransactionAttributeSource 主要是解析方法或类上的事务注解,封装成对应对象缓存

一个是 TransactionInterceptor 实现 MethodInterceptor 接口, 负责拦截指定方法, 处理事务(方法调用前获取连接,开启事务,方法调用后提交或回滚事务等等)

一个是 BeanFactoryTransactionAttributeSourceAdvisor 固定bean name 为 "org.springframework.transaction.config.internalTransactionAdvisor" 实现了Advisor接口

并通过名字引用了 TransactionInterceptor(Advice) , 且该类内部包含了  TransactionAttributeSourcePointcut (Pointcut)


OK 到这里, 事务的切面已经配置好了, 接下来要看Spring是怎么创建代理的吧. 前面注释中有说, 

如果配置了<aop:aspectj-autoproxy proxy-target-class="true" />, Spring就会注册一个bean定义 : AnnotationAwareAspectJAutoProxyCreator

这个类是实现了 BeanPostProcessor 在bean实例创建后, 会调用 BeanPostProcessor.postProcessAfterInitialization 方法来创建代理对象返回


在创建bean实例成功后, Spring自动调用所有实现了 BeanPostProcessor 接口的 bean 的 postProcessAfterInitialization 方法, 而AnnotationAwareAspectJAutoProxyCreator重写了该方法, 具体如下

//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;
    }
}


getAdvicesAndAdvisorsForBean方法内部通过内部在容器中找出所有的Advisor类型的bean,  然后根据条件来判断是否对当前bean应用Advisor.

这里事务是通过TransactionAttributeSourcePointcut继承而来的matches方法来判断, 而这个方法内部又是调用AnnotationTransactionAttributeSource的方法(判断是不是能取到事务配置).

源码大概路径是:

1.调用AbstractAdvisorAutoProxyCreator.findEligibleAdvisors()方法

    1.1调用AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()方法, 具体就是通过Advisor.class在bean工厂中找到所有匹配的bean

    1.2调用AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply()方法, 过滤掉不匹配的Advisor(具体过滤方法是调用AOPUtils.findAdvisorsThatCanApply()方法)

    1.3 AOPUtils.findAdvisorsThatCanApply() 方法内部又是通过调用TransactionAttributeSourcePointcut.getClassFilter().matches(targetClass)和getMethodMatcher().matches(method, targetClass)

          来过滤掉不符合的advisor.

2.调用AbstractAutoProxyCreator.createProxy()方法创建代理


到这里, 我们已经获取到了, 被作用了事务代理功能的bean实例, 接下来就是 方法调用的处理逻辑了. 博客字数限制, 下一篇再继续写.


转载于:https://my.oschina.net/haogrgr/blog/308199

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值