基于注解, 首先,我们会在配置文件中使用如下的配置来开启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实例, 接下来就是 方法调用的处理逻辑了. 博客字数限制, 下一篇再继续写.