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