Spring 源码解析(八)自定命名空间标签解析器 BeanDefinitionParser
自定义命名空间的每个标签都需要有去对应的解析器,且解析器需要实现BeanDefinitionParser,在parse方法中,解析将来在Spring配置文件中出现的标签元素。进入TxAdviceBeanDefinitionParser的parse方法(在org.springframework.beans.factory.xml.AbstractBeanDefinitionParser类实现)
//org.springframework.beans.factory.xml.AbstractBeanDefinitionParser
1 @Override 2 public final BeanDefinition parse(Element element, ParserContext parserContext) { 3 AbstractBeanDefinition definition = parseInternal(element, parserContext);//类定义 4 if (definition != null && !parserContext.isNested()) { 5 try { 6 String id = resolveId(element, definition, parserContext); 7 if (!StringUtils.hasText(id)) { 8 parserContext.getReaderContext().error( 9 "Id is required for element '" + parserContext.getDelegate().getLocalName(element) 10 + "' when used as a top-level tag", element); 11 } 12 String[] aliases = new String[0]; 13 String name = element.getAttribute(NAME_ATTRIBUTE); 14 if (StringUtils.hasLength(name)) { 15 aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name)); 16 } 17 BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases); 18 registerBeanDefinition(holder, parserContext.getRegistry()); 19 if (shouldFireEvents()) { 20 BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder); 21 postProcessComponentDefinition(componentDefinition); 22 parserContext.registerComponent(componentDefinition); 23 } 24 } 25 catch (BeanDefinitionStoreException ex) { 26 parserContext.getReaderContext().error(ex.getMessage(), element); 27 return null; 28 } 29 } 30 return definition; 31 }
第3行,解析标签为类定义AbstractBeanDefinition实例,跟进方法(org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser类实现)
//org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser
1 /** 2 * Creates a {@link BeanDefinitionBuilder} instance for the 3 * {@link #getBeanClass bean Class} and passes it to the 4 * {@link #doParse} strategy method. 5 * @param element the element that is to be parsed into a single BeanDefinition 6 * @param parserContext the object encapsulating the current state of the parsing process 7 * @return the BeanDefinition resulting from the parsing of the supplied {@link Element} 8 * @throws IllegalStateException if the bean {@link Class} returned from 9 * {@link #getBeanClass(org.w3c.dom.Element)} is {@code null} 10 * @see #doParse 11 */ 12 @Override 13 protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { 14 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); 15 String parentName = getParentName(element); 16 if (parentName != null) { 17 builder.getRawBeanDefinition().setParentName(parentName); 18 } 19 Class<?> beanClass = getBeanClass(element);//获取bean的类型Class对象 20 if (beanClass != null) { 21 builder.getRawBeanDefinition().setBeanClass(beanClass); 22 } 23 else { 24 String beanClassName = getBeanClassName(element);//获取类名 25 if (beanClassName != null) { 26 builder.getRawBeanDefinition().setBeanClassName(beanClassName); 27 } 28 } 29 builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); 30 if (parserContext.isNested()) { 31 // Inner bean definition must receive same scope as containing bean. 32 builder.setScope(parserContext.getContainingBeanDefinition().getScope()); 33 } 34 if (parserContext.isDefaultLazyInit()) { 35 // Default-lazy-init applies to custom bean definitions as well. 36 builder.setLazyInit(true); 37 } 38 doParse(element, parserContext, builder); 39 return builder.getBeanDefinition(); 40 }
第19行,查找bean的类型即Class对象,跟进方法(在org.springframework.transaction.config.TxAdviceBeanDefinitionParser类中实现)
//org.springframework.transaction.config.TxAdviceBeanDefinitionParser
1 @Override 2 protected Class<?> getBeanClass(Element element) { 3 return TransactionInterceptor.class; 4 }
<tx:advice/>标签解析,最后得到了一个className为TransactionInterceptor的BeanDefinition并注册。
我们看下TransactionInterceptor类的定义
1 /** 2 * AOP Alliance MethodInterceptor for declarative transaction 3 * management using the common Spring transaction infrastructure 4 * ({@link org.springframework.transaction.PlatformTransactionManager}). 5 * 6 * <p>Derives from the {@link TransactionAspectSupport} class which 7 * contains the integration with Spring's underlying transaction API. 8 * TransactionInterceptor simply calls the relevant superclass methods 9 * such as {@link #invokeWithinTransaction} in the correct order. 10 * 11 * <p>TransactionInterceptors are thread-safe. 12 * 13 * @author Rod Johnson 14 * @author Juergen Hoeller 15 * @see TransactionProxyFactoryBean 16 * @see org.springframework.aop.framework.ProxyFactoryBean 17 * @see org.springframework.aop.framework.ProxyFactory 18 */ 19 @SuppressWarnings("serial") 20 public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { 21 //省略代码 22 }
TransactionInterceptor实现了MethodInterceptor接口,所以这个类本质是一个Spring AOP 的advice,也就不难理解事物的配置能通过Spring AOP产生作用了。在此不分析事物处理的细节部分,对于Spring AOP需要读者有一定了解,在此也不在赘述。
★★★★★基于 <tx> 的事务管理示例配置文件★★★★★
1 <beans......> 2 ...... 3 <bean id="bankService" class="footmark.spring.core.tx.declare.namespace.BankServiceImpl"> 5 <property name="bankDao" ref="bankDao"/> 6 </bean> 7 <tx:advice id="bankAdvice" transaction-manager="transactionManager"> 8 <tx:attributes> 9 <tx:method name="transfer" propagation="REQUIRED"/> 10 </tx:attributes> 11 </tx:advice> 12 13 <aop:config> 14 <aop:pointcut id="bankPointcut" expression="execution(* *.transfer(..))"/> 15 <aop:advisor advice-ref="bankAdvice" pointcut-ref="bankPointcut"/> 16 </aop:config> 17 ...... 18 </beans>