• 设计配置属性和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;
}
												

spring 自定义解析类的更多相关文章

  1. Spring自定义转换类,让@Value更方便

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 前言 关于配置的文章已经写了很多,相信看过的人还是会有一定收获的,系列文章可阅读:南瓜慢说-配置相关文章.对于@Val ...

  2. Spring 自定义配置类bean

    <!-- 引入配置文件 --> <bean id="propertyConfigurer" class="org.springframework.bea ...

  3. spring自定义类中@AutoWired标识的元素注入为null

    最近在做项目的时候,发现程序运行的时候有一个nullpointer exception,一脸懵逼因为感觉程序没什么逻辑.后来发现是因为new出来的component不会自动注入它的元素. 现象:@Co ...

  4. spring 自定义标签的实现

    在我们进行Spring 框架开发中,估计用到最多的就是bean 标签吧,其实在Spring中像<mvc/><context/>这类标签以及在dubbo配置的标签都是属于自定义的 ...

  5. AutoMapper之自定义解析

    自定义解析 4.自定义解析 AutoMapper可以通过名称匹配等规则进行对象的映射,但是在实际的项目中,只是这样是远远不够的,比说我们需要名称不同的字段进行映射,或者需要再加一些逻辑处理.AutoM ...

  6. Spring自定义类扫描器 ClassPathScanningCandidateComponentProvider

    项目中有个需求 读取xml文件,然后 对xml文件进行解析,比如如果是 Gender=0/1的话,分别代表男女. 所以需要在构造函数之后,初始化bean之前进行过滤解析 xml文件: <inte ...

  7. spring源码分析系列 (5) spring BeanFactoryPostProcessor拓展类PropertyPlaceholderConfigurer、PropertySourcesPlaceholderConfigurer解析

    更多文章点击--spring源码分析系列 主要分析内容: 1.拓展类简述: 拓展类使用demo和自定义替换符号 2.继承图UML解析和源码分析 (源码基于spring 5.1.3.RELEASE分析) ...

  8. Spring自定义标签解析与实现

           在Spring Bean注册解析(一)和Spring Bean注册解析(二)中我们讲到,Spring在解析xml文件中的标签的时候会区分当前的标签是四种基本标签(import.alias ...

  9. [转载]开发 Spring 自定义视图和视图解析器

    原文出处 http://www.ibm.com/developerworks/cn/java/j-lo-springview/ 概述 Spring 3.0 默认包含了多种视图和视图解析器,比如 JSP ...

随机推荐

  1. python使用@property @x.setter @x.deleter

    @property可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/deleter也是需要的. 1>只有@property表示只读. 2>同时 ...

  2. Redis实现之对象(二)

    列表对象 列表对象的编码可以是ziplist或者linkedlist,ziplist编码的列表对象使用压缩列表作为底层实现,每个压缩列表节点(entry)保存了一个列表元素.举个栗子,如果我们执行RP ...

  3. laravel5.2总结--服务提供者,契约(Contracts)

    首先理解两个概念 1.契约:一组定义了框架核心服务的接口 2.服务提供者:所有 Laravel 应用程序启动的中心所在. 包括你自己的应用程序,以及所有的 Laravel 核心服务,都是通过服务提供者 ...

  4. Asp.net自定义控件开发任我行(3)-Render

    摘要 上一篇我们讲到了自定义标签TagPrefix用法,此篇我们来讲一下控件的呈现,主要是呈现下拉框 内容 呈现的方法有,Render,RenderControl,RenderChildren,这三个 ...

  5. leetcode 【 Trapping Rain Water 】python 实现

    题目: Given n non-negative integers representing an elevation map where the width of each bar is 1, co ...

  6. MFC定时关机程序的实现2-添加启动项到注册表

    虽然上一篇实现了的定时关机,但是还不够完善,比如开机自动启动,然后按照配置的时间定时关机,并最小化到任务栏. 先来说开机启动怎么实现,开机启动实现的方法有好几种,比如直接在开始菜单启动项里添加一个程序 ...

  7. ogre3D学习基础3 -- 粒子与表层脚本

    9.粒子脚本 粒子脚本允许你实例化地在你的脚本代码中定义粒子系统,而不必在源代码中进行设置,使得你做任何修改都能得到快速回应.脚本里定义的粒子系统被用作模板,并且多个实际的系统可以在运行时从这里被创建 ...

  8. tinyipa make

    参考:http://tinycorelinux.net/ Ironic Python Agent repo还提供了一组脚本,用于在imagebuild / tinyipa文件夹下构建一个基于Linux ...

  9. SRCNN(一)

    SRCNN学习(一):demo_SR.m 一.demo_SR.m 使用方法 1.Place the "SRCNN" folder into "($Caffe_Dir)/e ...

  10. HDU3232 Crossing Rivers 数学期望问题

    Crossing Rivers                                                                                     ...