首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

创设spring2.0命名空间?请用AbstractBeanDefintionParser

2012-09-23 
创建spring2.0命名空间?请用AbstractBeanDefintionParserCreating a Spring 2.0 namespace?Use Springs A

创建spring2.0命名空间?请用AbstractBeanDefintionParser
Creating a Spring 2.0 namespace? Use Spring's AbstractBeanDefintionParser hierarchy.

? 伟大的原文地址:http://blog.springsource.com/2006/08/28/creating-a-spring-20-namespace-use-springs-abstractbeandefintionparser-hierarchy/,以下为译文:

?

?

? 最近我热衷于创建spring xml命名空间,经过大量的尝试和错误后(既有xsd方面的也有spring方面的),总结出了一个比较好的基于parsers解析器的套路。最关键的是AbstractBeanDefinitionParser继承层次问题,这方面文档不全(but thereis a JIRA for it, so it'll be fixed before GA),我会给你一些选择建议:

选择使用哪一个AbstractBeanDefinitionParser?

spring提供给你了3个主要的bean定义解析器(BDP)来帮助你解析你的xml命名空间:

AbstractBeanDefinitionParserAbstractSingleBeanDefinitionParserAbstractSimpleBeanDefinitionParser

?

?

AbstractSimpleBeanDefinitionParser

? 最为特例化的BDP,该类用于xml标签属性与bean属性直接的情况(说白了就是这个BDP用于处理只具有属性的xml元素的解析)。示例:

<util:properties location = "..." />

public class PropertiesFactoryBean extends PropertiesLoaderSupport implements FactoryBean, InitializingBean { ... public void setLocation(Resource location) { this.locations = new Resource[] {location}; } ...}

?

? util:properties元素的location属性匹配了PropertiesFactoryBean 的一个同名属性set方法,AbstractSimpleBeanDefinitionParser会自动赋值,你只需要在你的BDP实现一个getBeanClass()方法:

public class PropertiesBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {     protected Class getBeanClass(Element element) {        return PropertiesFactoryBean.class;    }}

? 玩java的你懂的,毋庸多言。

?

?

AbstractSingleBeanDefinitionParser

? AbstractSingleBeanDefinitionParser更通用一点,我觉得应该是最常用的一个,用它你可以创建任意的单独bean定义,并自动化的注册到context。这里的bean就不会再只有简单的属性映射了,它可能具有一个复杂的嵌套结构,但无论怎样它都只创建一个bean定义:

<tx:advice>    <tx:attributes>        <tx:method name="get*" read-only="false" />    </tx:attributes></tx:advice>

?对应类:

public class TransactionInterceptor extends TransactionAspectSupport    implements MethodInterceptor, Serializable {    ...    public void setTransactionAttributes(Properties transactionAttributes) {        NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();        tas.setProperties(transactionAttributes);        this.transactionAttributeSource = tas;    }    ...}

? tx:advice元素具有一个复杂嵌套结构,在你的BDP:AbstractSingleBeanDefinitionParser当中你可以直接浏览DOM结构来处理:

class TxAdviceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {    ...    protected void doParse(Element element, BeanDefinitionBuilder builder) {        // Set the transaction manager property.        builder.addPropertyReference(TxNamespaceUtils.TRANSACTION_MANAGER_PROPERTY,            element.getAttribute(TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE));         List txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES);        if (txAttributes.size() > 1) {            throw new IllegalStateException("Element 'attributes' is allowed at most once inside element 'advice'");        }        else if (txAttributes.size() == 1) {            // Using attributes source.            parseAttributes((Element) txAttributes.get(0), builder);        }        else {            // Assume annotations source.            Class sourceClass = TxNamespaceUtils.getAnnotationTransactionAttributeSourceClass();            builder.addPropertyValue(TxNamespaceUtils.TRANSACTION_ATTRIBUTE_SOURCE, new RootBeanDefinition(sourceClass));        }    }    ...}

? 这应该是最常用最灵活的方式来做:bean definition parsing.

?

?

AbstractBeanDefinitionParser

? 这个BDP不仅允许你创建一个bean定义,而且给你提供了足够的玩意去创建多个bean定义:

<tx:annotation-driven />

? 熟悉Spring 2.0及其新的命名空间的人应该很熟悉这个标签,它自动地侦测@Transactional注解并代理注解所在类,和你在Spring 1.2.8里创建DefaultAutoProxyCreator一样,一系列的bean定义会被创建出来,一共4个:

class AnnotationDrivenBeanDefinitionParser extends AbstractBeanDefinitionParser {    ...protected BeanDefinition parseInternal(Element element, ParserContext parserContext) {         // Register the APC if needed.        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext);         boolean proxyTargetClass = TRUE.equals(element.getAttribute(PROXY_TARGET_CLASS));        if (proxyTargetClass) {            AopNamespaceUtils.forceAutoProxyCreatorToUseClassProxying(parserContext.getRegistry());        }         String transactionManagerName = element.getAttribute(TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE);        Class sourceClass = TxNamespaceUtils.getAnnotationTransactionAttributeSourceClass();         // Create the TransactionInterceptor definition        RootBeanDefinition interceptorDefinition = new RootBeanDefinition(TransactionInterceptor.class);        interceptorDefinition.getPropertyValues().addPropertyValue(            TxNamespaceUtils.TRANSACTION_MANAGER_PROPERTY, new RuntimeBeanReference(transactionManagerName));        interceptorDefinition.getPropertyValues().addPropertyValue(            TxNamespaceUtils.TRANSACTION_ATTRIBUTE_SOURCE, new RootBeanDefinition(sourceClass));         // Create the TransactionAttributeSourceAdvisor definition.        RootBeanDefinition advisorDefinition = new RootBeanDefinition(TransactionAttributeSourceAdvisor.class);        advisorDefinition.getPropertyValues().addPropertyValue(TRANSACTION_INTERCEPTOR, interceptorDefinition);        return advisorDefinition;    }    ...}

? 由于给你提供了ParserContext,所以允许你创建自己的bean定义并直接注册。

?

?

So which to use?

It's actually a pretty easy progression. Use AbstractSimpleBeanDefinitionParser if there is a direct correlation between attributes on a tag and properties on a bean. Use AbstractSingleBeanDefinitionParser if you are creating a single bean definition that requires you to do some DOM traversal. If the first two are too constrictive and you want to be able to arbitrarily register your own beans, use AbstractBeanDefinitionParser. Finally if you really like going it on your own you can always directly implement the BeanDefinitionParser interface yourself.

So there you have it, a quick intro to bean definition parsing. What I'd like to know is how many of you are doing this? What have you created namespaces for and how are you using the parser hierarchy? Use the comments to have your voice heard. Who knows, your experiences and suggestions may make there way into a JIRA as an enhancement…

?