2. 命名空间及自定义标签的解析

从上一篇文章中可以知道《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);
	}

至此,已经找到自定义命名空间和标签的解析器,该过程主要分为以下几步:

  1. 获取所有META-INF/spring.handlers中的自定义标签命名空间和命名空间处理器的映射关系
  2. 调用命名空间处理器的init()方法注册标签解析器
  3. 调用相对应的解析器的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。
但是,我们并没有在这个解析中看到事务相关的实质性的内容,例如:

  1. @Transactional事务注解的解析
  2. 在什么场景下需要进行事务的增强
  3. 如何进行事务的增强

从前面的分析中我们并找到通过某个方法的调用去实现事务功能,好像走进了一条死胡同。当细心的读者会发现,在注册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/>的解析过程。总结下整个解析步骤:

  1. 通过命名空间获取命名空间处理类,并在命名空间处理类中注册解析器
  2. 通过解析器解析自定义标签<tx:annotation-driven/>,解析目的主要是向容器中注册四个bean
  3. 在BeanPostProcessor中判断哪些bean需要被增强,如果需要,则创建bean的动态代理对象,并返回
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值