zoukankan      html  css  js  c++  java
  • spring 自定义解析类

    • 设计配置属性和JavaBean
    • 编写XSD文件
    • 编写NamespaceHandler和BeanDefinitionParser完成解析工作
    • 编写spring.handlers和spring.schemas串联起所有部件
    • 在Bean文件中应用

    会用到NamespaceHandler和BeanDefinitionParser这两个概念。具体说来NamespaceHandler会根据schema和节点名找到某个BeanDefinitionParser,然后由BeanDefinitionParser完成具体的解析工作。因此需要分别完成NamespaceHandler和BeanDefinitionParser的实现类,Spring提供了默认实现类NamespaceHandlerSupport和AbstractSingleBeanDefinitionParser,简单的方式就是去继承这两个类。
    先看个示例吧。spring  scheduling命名空间下的   scheduled-tasks 解析。

    /**
    * Parser for the 'scheduled-tasks' element of the scheduling namespace.
    *
    * @author Mark Fisher
    * @author Chris Beams
    * @since 3.0
    */
    public class ScheduledTasksBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    private static final String ELEMENT_SCHEDULED = "scheduled";

    private static final long ZERO_INITIAL_DELAY = 0;

    //解析方法
    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
    builder.setLazyInit(false); // lazy scheduled tasks are a contradiction in terms -> force to false
    ManagedList<RuntimeBeanReference> cronTaskList = new ManagedList<>();
    ManagedList<RuntimeBeanReference> fixedDelayTaskList = new ManagedList<>();
    ManagedList<RuntimeBeanReference> fixedRateTaskList = new ManagedList<>();
    ManagedList<RuntimeBeanReference> triggerTaskList = new ManagedList<>();
    NodeList childNodes = element.getChildNodes();
    for (int i = 0; i < childNodes.getLength(); i++) {
    Node child = childNodes.item(i);
    if (!isScheduledElement(child, parserContext)) {
    continue;
    }
    Element taskElement = (Element) child;
    String ref = taskElement.getAttribute("ref");
    String method = taskElement.getAttribute("method");

    // Check that 'ref' and 'method' are specified
    if (!StringUtils.hasText(ref) || !StringUtils.hasText(method)) {
    parserContext.getReaderContext().error("Both 'ref' and 'method' are required", taskElement);
    // Continue with the possible next task element
    continue;
    }

    String cronAttribute = taskElement.getAttribute("cron");
    String fixedDelayAttribute = taskElement.getAttribute("fixed-delay");
    String fixedRateAttribute = taskElement.getAttribute("fixed-rate");
    String triggerAttribute = taskElement.getAttribute("trigger");
    String initialDelayAttribute = taskElement.getAttribute("initial-delay");

    boolean hasCronAttribute = StringUtils.hasText(cronAttribute);
    boolean hasFixedDelayAttribute = StringUtils.hasText(fixedDelayAttribute);
    boolean hasFixedRateAttribute = StringUtils.hasText(fixedRateAttribute);
    boolean hasTriggerAttribute = StringUtils.hasText(triggerAttribute);
    boolean hasInitialDelayAttribute = StringUtils.hasText(initialDelayAttribute);

    if (!(hasCronAttribute || hasFixedDelayAttribute || hasFixedRateAttribute || hasTriggerAttribute)) {
    parserContext.getReaderContext().error(
    "one of the 'cron', 'fixed-delay', 'fixed-rate', or 'trigger' attributes is required", taskElement);
    continue; // with the possible next task element
    }

    if (hasInitialDelayAttribute && (hasCronAttribute || hasTriggerAttribute)) {
    parserContext.getReaderContext().error(
    "the 'initial-delay' attribute may not be used with cron and trigger tasks", taskElement);
    continue; // with the possible next task element
    }

    String runnableName =
    runnableReference(ref, method, taskElement, parserContext).getBeanName();

    if (hasFixedDelayAttribute) {
    fixedDelayTaskList.add(intervalTaskReference(runnableName,
    initialDelayAttribute, fixedDelayAttribute, taskElement, parserContext));
    }
    if (hasFixedRateAttribute) {
    fixedRateTaskList.add(intervalTaskReference(runnableName,
    initialDelayAttribute, fixedRateAttribute, taskElement, parserContext));
    }
    if (hasCronAttribute) {
    cronTaskList.add(cronTaskReference(runnableName, cronAttribute,
    taskElement, parserContext));
    }
    if (hasTriggerAttribute) {
    String triggerName = new RuntimeBeanReference(triggerAttribute).getBeanName();
    triggerTaskList.add(triggerTaskReference(runnableName, triggerName,
    taskElement, parserContext));
    }
    }
    String schedulerRef = element.getAttribute("scheduler");
    if (StringUtils.hasText(schedulerRef)) {
    builder.addPropertyReference("taskScheduler", schedulerRef);
    }
    builder.addPropertyValue("cronTasksList", cronTaskList);
    builder.addPropertyValue("fixedDelayTasksList", fixedDelayTaskList);
    builder.addPropertyValue("fixedRateTasksList", fixedRateTaskList);
    builder.addPropertyValue("triggerTasksList", triggerTaskList);
    }

    以上就是默认的xml解析

    注解解析的类是 AnnotationDrivenBeanDefinitionParser


    /**
    * Parser for the 'annotation-driven' element of the 'task' namespace.
    *
    * @author Mark Fisher
    * @author Juergen Hoeller
    * @author Ramnivas Laddad
    * @author Chris Beams
    * @author Stephane Nicoll
    * @since 3.0
    */
    public class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {

    private static final String ASYNC_EXECUTION_ASPECT_CLASS_NAME =
    "org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect";



    //解析方法

    @Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
    Object source = parserContext.extractSource(element);

    // Register component for the surrounding <task:annotation-driven> element.
    CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
    parserContext.pushContainingComponent(compDefinition);

    // Nest the concrete post-processor bean in the surrounding component.
    BeanDefinitionRegistry registry = parserContext.getRegistry();

    String mode = element.getAttribute("mode");
    if ("aspectj".equals(mode)) {
    // mode="aspectj"
    registerAsyncExecutionAspect(element, parserContext);
    }
    else {
    // mode="proxy"
    if (registry.containsBeanDefinition(TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    parserContext.getReaderContext().error(
    "Only one AsyncAnnotationBeanPostProcessor may exist within the context.", source);
    }
    else {
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
    "org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor");
    builder.getRawBeanDefinition().setSource(source);
    String executor = element.getAttribute("executor");
    if (StringUtils.hasText(executor)) {
    builder.addPropertyReference("executor", executor);
    }
    String exceptionHandler = element.getAttribute("exception-handler");
    if (StringUtils.hasText(exceptionHandler)) {
    builder.addPropertyReference("exceptionHandler", exceptionHandler);
    }
    if (Boolean.valueOf(element.getAttribute(AopNamespaceUtils.PROXY_TARGET_CLASS_ATTRIBUTE))) {
    builder.addPropertyValue("proxyTargetClass", true);
    }
    registerPostProcessor(parserContext, builder, TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME);
    }
    }

    if (registry.containsBeanDefinition(TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    parserContext.getReaderContext().error(
    "Only one ScheduledAnnotationBeanPostProcessor may exist within the context.", source);
    }
    else {
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
    "org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor");
    builder.getRawBeanDefinition().setSource(source);
    String scheduler = element.getAttribute("scheduler");
    if (StringUtils.hasText(scheduler)) {
    builder.addPropertyReference("scheduler", scheduler);
    }
    registerPostProcessor(parserContext, builder, TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME);
    }

    // Finally register the composite component.
    parserContext.popAndRegisterContainingComponent();

    return null;
    }






  • 相关阅读:
    excel表格的jar包
    mac和jar的关系
    BAT批处理文件入门-笔记
    没看完_perl的find模块很全面的讲解!!
    perl怎么拷贝一个文件到另一个文件夹中或者怎么拷贝文件夹到另一个文件夹
    perl 中用到的-*的具体解释,方便查看
    perl语言的笔记--啥是mkpath
    剑指哦佛_我的第一篇博客,哦耶
    ajax创建万能的XmlHttpRequest对象
    动态实例化窗体
  • 原文地址:https://www.cnblogs.com/anyehome/p/10186821.html
Copyright © 2011-2022 走看看