从上一篇文章中可以知道《Spring事务实现概览》中可以知道<tx:annotation-driven>为整个事务实现的入口。通过对该标签的解析来实现事务的管理。
本文以<tx:annotation-driven>为入口,分析tx自定义标签。
1. 自定义标签解析入口
spring bean容器在解析配置文件的时候,除了正常解析<bean>外,还提供了自定义命名空间的解析入口(真的强大👍),那么我们就以XmlBeanFactory为入口,找到自定义标签解析入口
XmlBeanFactory.java
/**
*通过给定的资源创建XmlBeanFactory容器,资源就是配置文件,即上一篇文章中的context.xml
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);//加载beanDefinition
}
XmlBeanDefinitionReader.java中解析xml文件:
/**
*实际从xml中加载bean definition的入口
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);//将resource转化为Document
int count = registerBeanDefinitions(doc, resource);//注册beanDefinition
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (... ex) {//省略catch代码
throw ex;
}
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//DefaultBeanDefinitionDocumentReader
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//注册
return getRegistry().getBeanDefinitionCount() - countBefore;
}
DefaultBeanDefinitionDocumentReader.java
/**
*解析<beans/>下的标签
*/
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
...
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);//解析beanDefinition
postProcessXml(root);
...
}
/**
* Parse the elements at the root level in the document:
* "import", "alias", "bean".
* @param root the DOM root element of the document
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);//解析默认元素,即<bean/>
}
else {
delegate.parseCustomElement(ele);//解析自定义元素,这就是解析<tx:annotation-driven/>的入口
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
@Nullable
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//解析META-INF/spring.handlers,获取NamespaceHandler,并调用init()方法进行注册每一个标签的解析器
//tx命名空间使用的是TxNamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);//DefaultNamespaceHandlerResolver.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));//自定义标签的解析,TxNamespaceHandler
}
已经找到自定义标签的解析入口,并获取到TxNamespaceHandler对象,通过调用TxNamespaceHandler的parse方法对<tx:>命名空间中的不同标签进行解析。
2. 确定<tx:annotation-driven>标签解析器
TxNamespaceHandler.java
public class TxNamespaceHandler extends NamespaceHandlerSupport {
static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";
//如果<annotation-driven/>标签没配置transaction-manager属性,那么默认为transactionManager
static String getTransactionManagerName(Element element) {
return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
}
//初始化,注册不同tx命名空间内不同标签的解析器
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());//annotation-driven标签解析器
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
}
NamespaceHandlerSupport.java
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//TxNamespaceHandler中注册的parser,此处分析AnnotationDrivenBeanDefinitionParser(init中注册的)
BeanDefinitionParser parser = findParserForElement(element, parserContext);
return (parser != null ? parser.parse(element, parserContext) : null);
}
至此,已经找到自定义命名空间和标签的解析器,该过程主要分为以下几步:
- 获取所有META-INF/spring.handlers中的自定义标签命名空间和命名空间处理器的映射关系
- 调用命名空间处理器的init()方法注册标签解析器
- 调用相对应的解析器的parse方法解析自定义标签(AnnotationDrivenBeanDefinitionParser.parse)
接下来就是对自定义标签<tx:annotation-driven/>的具体解析过程。
2. 解析事务自定义标签<tx:annotation-driven/>
package org.springframework.transaction.config;
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
/**
* 解析<tx:annotation-driven/>标签,并注册一个AutoProxyCreator
*/
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册事务事件监听器工厂,用于事务绑定事件
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
//aspectj代理模式
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
registerJtaTransactionAspect(element, parserContext);
}
}
else {
// mode="proxy",基于动态代理的
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
//设置属性值
private static void registerTransactionManager(Element element, BeanDefinition def) {
def.getPropertyValues().add("transactionManagerBeanName",
TxNamespaceHandler.getTransactionManagerName(element));
}
private static class AopAutoProxyConfigurer {
/**
* 主要功能是在容器中注册四个beanDefinition
* 1. InfrastructureAdvisorAutoProxyCreator:实现BeanPostProcessor增强bean
* 2. TransactionAttributeSourceAdvisor:封装TransactionInterceptor和pointcut
* 3. AnnotationTransactionAttributeSource:通过getTransactionAttribute(Method method, @Nullable Class<?> targetClass);方法来获取@Transactional注解中的事务属性
* 4. TransactionInterceptor:事务拦截器处理类,对事务做增强处理
*/
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//注册InfrastructureAdvisorAutoProxyCreator的BeanDefinition
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
// 创建TransactionAttributeSource definition.
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);//注册AnnotationTransactionAttributeSource的BeanDefinition
// 创建TransactionInterceptor definition.
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerTransactionManager(element, interceptorDef);//添加transactionManagerBeanName属性
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));//添加sourceName属性
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);//注册TransactionInterceptor的BeanDefinition
// 创建TransactionAttributeSourceAdvisor definition.
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));//添加sourceName属性
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);//添加interceptorName属性
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));//Advisor优先级
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);//注册advisor的BeanDefinition
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/>标签的解析以及完成了。其目的就是在容器中注册4个BeanDefinition。
但是,我们并没有在这个解析中看到事务相关的实质性的内容,例如:
- @Transactional事务注解的解析
- 在什么场景下需要进行事务的增强
- 如何进行事务的增强
从前面的分析中我们并找到通过某个方法的调用去实现事务功能,好像走进了一条死胡同。当细心的读者会发现,在注册BeanDefinition的时候有一个InfrastructureAdvisorAutoProxyCreator类型的BeanDefinition,同时InfrastructureAdvisorAutoProxyCreator实现了BeanPostProcessor接口。
关于BeanPostProcessor请参考另一篇文章xxxx
通过BeanPostProcessor的特性,我们可以知道,在容器中的BeanDefinition实例化前后悔调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法。InfrastructureAdvisorAutoProxyCreator的间接父类AbstractAutoProxyCreator中实现了这两个方法
AbstractAutoProxyCreator.java
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
//创建代理类
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
/**
* 如果需要的话,对闯入的对象做合适的代理
* @param 原有bean
* @param 原有bean的名称
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//该类已处理过,无需代理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//基础框架的类不需要被代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获取Advisor, 如果有的话创建代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建bean实例的代理
//JDK动态代理的InvocationHandler为JdkDynamicAopProxy
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
AbstractAdvisorAutoProxyCreator.java
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//获取合适的Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
/**
* Find all eligible Advisors for auto-proxying this class.
* @param beanClass the clazz to find advisors for
* @param beanName the name of the currently proxied bean
* @return the empty List, not {@code null},
* if there are no pointcuts or interceptors
* @see #findCandidateAdvisors
* @see #sortAdvisors
* @see #extendAdvisors
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取候选Advisors,即Advisor类型的所有bean,这里实际获取到的Advisor为BeanFactoryTransactionAttributeSourceAdvisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//需要应用于bean实例类的Advisor列表
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
//将Advisor列表按优先级排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
/**
* 判断候选的Advisor是否应该被应用
*
*/
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
AopUtils.java
/**
* 从候选的Advisor中查找需要应用于clazz类的Advisor列表
* 这里的候选Advisor只有BeanFactoryTransactionAttributeSourceAdvisor,它实现了PointCutAdvisor接口
*/
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//判断是否需要应用Advisor
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
/**
* 是否需要应用Advisor
*/
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {//走该分支
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();//pc为TransactionAttributeSourcePointcut类型
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
//遍历所有接口
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {//遍历接口中的所有方法
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
//匹配是否需要代理,methodMatcher为TransactionAttributeSourcePointcut类型
//只要有一个方法匹配成功,那么这个bean就需要被增强
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
TransactionAttributeSourcePointcut.java
/**
* 解析得到的@Transactional属性信息不为空,则匹配成功
*/
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
//对已解析的数据做缓存,如果缓存中有则直接返回
Object cacheKey = getCacheKey(method, targetClass);
Object cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return (TransactionAttribute) cached;
}
}
else {
// We need to work it out.
//获取@Transactional注解中的属性,
//1. 方法注解优先于类注解
//2. 实现类注解优先于接口注解
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
//将属性信息放入缓存中,如果没有则缓存value为空的DefaultTransactionAttribute对象
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;
}
}
通过BeanPostProcessor,会对每个一个bean进行判断是否需要动态代理增强,判断条件为接口方法和类是否存在@Transactional注解,如果存在该注解,则需要对这个bean进行增强,如果不存在则不需要增强。
动态代理类的InvocationHandler为JdkDynamicAopProxy。即在JdkDynamicAopProxy中完成了事务的创建,提交,挂起,回滚等操作。
是的,到目前为止,我们已经完成了自定义标签<tx:annotation-driven/>的解析过程。总结下整个解析步骤:
- 通过命名空间获取命名空间处理类,并在命名空间处理类中注册解析器
- 通过解析器解析自定义标签<tx:annotation-driven/>,解析目的主要是向容器中注册四个bean
- 在BeanPostProcessor中判断哪些bean需要被增强,如果需要,则创建bean的动态代理对象,并返回