Spring 源码解析八:Xml 配置中默认的命名空间处理器

Spring 源码解析八:Xml 配置中默认的命名空间处理器

Spring 源码解析五:Bean 的配置、定义、注册 中,有一些 Xml 配置中默认的命名空间处理器还未解析

这里只解析常用的几个

  • SimpleConstructorNamespaceHandler
  • SimplePropertyNamespaceHandler
  • ContextNamespaceHandler
  • TaskNamespaceHandler
  • CacheNamespaceHandler
  • MvcNamespaceHandler

其他的有兴趣可以自行探索

1. SimpleConstructorNamespaceHandler

SimpleConstructorNamespaceHandler
的主要功能是在实例化如下配置的 bean

name="Enescu", work=bean[compositions] 作为构造函数的参数实例化 bean

public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
    @Override
    public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
        if (node instanceof Attr) {
            Attr attr = (Attr) node;
            // 去除两边空白
            String argName = StringUtils.trimWhitespace(parserContext.getDelegate().getLocalName(attr));
            // 去除两边空白
            String argValue = StringUtils.trimWhitespace(attr.getValue());

            // 构造函数参数集合
            ConstructorArgumentValues cvs = definition.getBeanDefinition().getConstructorArgumentValues();
            boolean ref = false;

            // 如果字段名以"-ref"结果,则表示在运行时对其他bean的引用
            if (argName.endsWith(REF_SUFFIX)) {
                ref = true;
                argName = argName.substring(0, argName.length() - REF_SUFFIX.length());
            }

            // 用ValueHolder封装值
            ValueHolder valueHolder = new ValueHolder(ref ? new RuntimeBeanReference(argValue) : argValue);
            valueHolder.setSource(parserContext.getReaderContext().extractSource(attr));

            // 以"_"开头的,表示是没有名字的参数,按照顺序传入就可以了
            if (argName.startsWith(DELIMITER_PREFIX)) {
                String arg = argName.substring(1).trim();

                // 如果没有指定顺序,直接添加
                if (!StringUtils.hasText(arg)) {
                    cvs.addGenericArgumentValue(valueHolder);
                }
                // 如果有指定顺序,指定顺序添加
                else {
                    int index = -1;
                    try {
                        index = Integer.parseInt(arg);
                    }
                    catch (NumberFormatException ex) {
                        // ... 代码省略
                    }

                    // ... 代码省略

                    // 添加进cvs
                    cvs.addIndexedArgumentValue(index, valueHolder);
                }
            }
            // 有名字的参数
            else {
                // ... 代码省略

                // 添加进cvs
                valueHolder.setName(Conventions.attributeNameToPropertyName(argName));
                cvs.addGenericArgumentValue(valueHolder);
            }
        }
        return definition;
    }
}

2. SimplePropertyNamespaceHandler

SimplePropertyNamespaceHandler
的主要功能是在实例化如下配置的 bean

name="Rob Harrop", spouse=bean[sally] 作为属性注入到 bean 中

public class SimplePropertyNamespaceHandler implements NamespaceHandler {
    @Override
    public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
        if (node instanceof Attr) {
            Attr attr = (Attr) node;
            // 属性名
            String propertyName = parserContext.getDelegate().getLocalName(attr);
            // 属性值
            String propertyValue = attr.getValue();
            // 属性集合
            MutablePropertyValues pvs = definition.getBeanDefinition().getPropertyValues();

            // 如果字段名以"-ref"结果,则表示在运行时对其他bean的引用
            if (propertyName.endsWith(REF_SUFFIX)) {
                propertyName = propertyName.substring(0, propertyName.length() - REF_SUFFIX.length());
                // 把字段名从短横线-或下划线_式的,转化为驼峰式的
                pvs.add(Conventions.attributeNameToPropertyName(propertyName), new RuntimeBeanReference(propertyValue));
            }
            else {
                // 把字段名从短横线-或下划线_式的,转化为驼峰式的
                pvs.add(Conventions.attributeNameToPropertyName(propertyName), propertyValue);
            }
        }
        return definition;
    }
}

3. ContextNamespaceHandler

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
        registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
        registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
        registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
        registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
    }
}

3.1. context:property-placeholder

PropertyPlaceholderBeanDefinitionParser
的主要功能是解析元素,在 bean 定义时,使用 ${} 引用外部来源的属性

先看看继承关系

- AbstractBeanDefinitionParser
  - AbstractSingleBeanDefinitionParser
    - AbstractPropertyLoadingBeanDefinitionParser
      - PropertyPlaceholderBeanDefinitionParser

3.1.1. AbstractBeanDefinitionParser

AbstractBeanDefinitionParser
的主要功能是实现了 BeanDefinitionParser
接口的 parse 方法,提供了基本的由配置解析为对象的功能

public abstract class AbstractBeanDefinitionParser implements BeanDefinitionParser {
    @Override
    public final BeanDefinition parse(Element element, ParserContext parserContext) {
        // 解析元素
        AbstractBeanDefinition definition = parseInternal(element, parserContext);

        try {
            // 获取bean的id
            String id = resolveId(element, definition, parserContext);

            String[] aliases = null;
            // 获取name属性,用逗号分隔为多个别名
            if (shouldParseNameAsAliases()) {
                String name = element.getAttribute(NAME_ATTRIBUTE);
                if (StringUtils.hasLength(name)) {
                    aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
                }
            }

            // 封装为BeanDefinitionHolder
            BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
            // 注册到registry中
            registerBeanDefinition(holder, parserContext.getRegistry());

            // ... 代码省略
        }
        catch (BeanDefinitionStoreException ex) {
            // ... 代码省略
        }
        return definition;
    }

    // 解析元素,由子类实现
    protected abstract AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext);

    // 获取bean的id,先获取id属性,其次name属性,都没有,生成默认的名字
    protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
            throws BeanDefinitionStoreException {
        // ... 代码省略
    }
}

3.1.2. AbstractSingleBeanDefinitionParser

AbstractSingleBeanDefinitionParser
的主要功能是支持解析为单例的 bean

public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDefinitionParser {
    @Override
    protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
        // 创建一个构造器
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        // 父元素
        String parentName = getParentName(element);
        if (parentName != null) {
            builder.getRawBeanDefinition().setParentName(parentName);
        }
        // beanClass
        Class beanClass = getBeanClass(element);
        if (beanClass != null) {
            builder.getRawBeanDefinition().setBeanClass(beanClass);
        }
        // beanClassName
        else {
            String beanClassName = getBeanClassName(element);
            if (beanClassName != null) {
                builder.getRawBeanDefinition().setBeanClassName(beanClassName);
            }
        }

        // ... 代码省略

        // 解析到构造器
        doParse(element, parserContext, builder);
        return builder.getBeanDefinition();
    }

    // 解析到构造器,由子类实现
    protected void doParse(Element element, BeanDefinitionBuilder builder) {}
}

3.1.3. AbstractPropertyLoadingBeanDefinitionParser

AbstractPropertyLoadingBeanDefinitionParser
的主要功能是解析context:property-...元素

abstract class AbstractPropertyLoadingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        // location属性
        String location = element.getAttribute("location");
        if (StringUtils.hasLength(location)) {
            location = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(location);
            String[] locations = StringUtils.commaDelimitedListToStringArray(location);
            builder.addPropertyValue("locations", locations);
        }

        // properties-ref属性
        String propertiesRef = element.getAttribute("properties-ref");
        if (StringUtils.hasLength(propertiesRef)) {
            builder.addPropertyReference("properties", propertiesRef);
        }

        // file-encoding属性
        String fileEncoding = element.getAttribute("file-encoding");
        if (StringUtils.hasLength(fileEncoding)) {
            builder.addPropertyValue("fileEncoding", fileEncoding);
        }

        // order属性
        String order = element.getAttribute("order");
        if (StringUtils.hasLength(order)) {
            builder.addPropertyValue("order", Integer.valueOf(order));
        }

        // ignore-resource-not-found属性
        builder.addPropertyValue("ignoreResourceNotFound",
                Boolean.valueOf(element.getAttribute("ignore-resource-not-found")));

        // local-override属性
        builder.addPropertyValue("localOverride",
                Boolean.valueOf(element.getAttribute("local-override")));
    }
}

3.1.4. PropertyPlaceholderBeanDefinitionParser

PropertyPlaceholderBeanDefinitionParser
的主要功能是解析context:property-placeholder元素

class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBeanDefinitionParser {
    @Override
    protected Class getBeanClass(Element element) {
        // 使用这个类来实现bean
        return org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.class;
    }

    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        super.doParse(element, parserContext, builder);

        // ignore-unresolvable属性
        builder.addPropertyValue("ignoreUnresolvablePlaceholders",
                Boolean.valueOf(element.getAttribute("ignore-unresolvable")));

        // system-properties-mode属性
        String systemPropertiesModeName = element.getAttribute(SYSTEM_PROPERTIES_MODE_ATTRIBUTE);
        if (StringUtils.hasLength(systemPropertiesModeName) &&
                !systemPropertiesModeName.equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) {
            builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_" + systemPropertiesModeName);
        }

        // value-separator属性
        if (element.hasAttribute("value-separator")) {
            builder.addPropertyValue("valueSeparator", element.getAttribute("value-separator"));
        }
        // trim-values属性
        if (element.hasAttribute("trim-values")) {
            builder.addPropertyValue("trimValues", element.getAttribute("trim-values"));
        }
        // null-value属性
        if (element.hasAttribute("null-value")) {
            builder.addPropertyValue("nullValue", element.getAttribute("null-value"));
        }
    }
}

3.2. context:property-override

PropertyOverrideBeanDefinitionParser
的主要功能是解析元素,为 xml 配置文件中的 bean 的属性指定最终结果

class PropertyOverrideBeanDefinitionParser extends AbstractPropertyLoadingBeanDefinitionParser {
    @Override
    protected Class getBeanClass(Element element) {
        // 使用这个类来实现bean
        return PropertyOverrideConfigurer.class;
    }

    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        super.doParse(element, parserContext, builder);

        // ignore-unresolvable属性
        builder.addPropertyValue("ignoreInvalidKeys",
                Boolean.valueOf(element.getAttribute("ignore-unresolvable")));

    }
}

3.3. context:annotation-config

AnnotationConfigBeanDefinitionParser
的主要功能是解析元素,使用 @Autowired 自动装配 bean

public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        Object source = parserContext.extractSource(element);

        // 获取registry所有相关的bean定义
        Set processorDefinitions =
                AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);

        // ... 代码省略

        // 注册bean定义
        for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
            parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
        }

        // ... 代码省略

        return null;
    }
}

3.4. context:component-scan

ComponentScanBeanDefinitionParser
的主要功能是解析元素,自动扫描指定包下的注解 bean

public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // base-package属性
        String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
        basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
        // 分隔多个包
        String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

        // 创建并配置扫描对象
        ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
        // 扫描包中的组件
        Set beanDefinitions = scanner.doScan(basePackages);
        // 注册组件到上下文中
        registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

        return null;
    }
}

关于 context: 命令空间的解析就到这里了,其他的有兴趣可以自行探索

4. TaskNamespaceHandler

public class TaskNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        this.registerBeanDefinitionParser("executor", new ExecutorBeanDefinitionParser());
        this.registerBeanDefinitionParser("scheduled-tasks", new ScheduledTasksBeanDefinitionParser());
        this.registerBeanDefinitionParser("scheduler", new SchedulerBeanDefinitionParser());
    }
}

4.1. task:annotation-driven

AnnotationDrivenBeanDefinitionParser
的主要功能是解析元素,开启定时器开关,自动扫描程序中带注解的定时器

public class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        Object source = parserContext.extractSource(element);

        // ... 代码省略

        // 获取registry
        BeanDefinitionRegistry registry = parserContext.getRegistry();

        // mode属性
        String mode = element.getAttribute("mode");
        // 使用aspectj来执行异步任务
        if ("aspectj".equals(mode)) {
            // mode="aspectj"
            registerAsyncExecutionAspect(element, parserContext);
        }
        // 使用内置的功能来执行异步任务
        else {
            // bean "org.springframework.context.annotation.internalAsyncAnnotationProcessor" 已经存在
            if (registry.containsBeanDefinition(TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                // ... 代码省略
            }
            else {
                // 使用类 "org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor"
                // 来配置bean "org.springframework.context.annotation.internalAsyncAnnotationProcessor"
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
                        "org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor");
                builder.getRawBeanDefinition().setSource(source);
                // executor属性
                String executor = element.getAttribute("executor");
                if (StringUtils.hasText(executor)) {
                    builder.addPropertyReference("executor", executor);
                }
                // exception-handler属性
                String exceptionHandler = element.getAttribute("exception-handler");
                if (StringUtils.hasText(exceptionHandler)) {
                    builder.addPropertyReference("exceptionHandler", exceptionHandler);
                }
                // proxy-target-class属性
                if (Boolean.parseBoolean(element.getAttribute(AopNamespaceUtils.PROXY_TARGET_CLASS_ATTRIBUTE))) {
                    builder.addPropertyValue("proxyTargetClass", true);
                }
                // 注册组件到registry与上下文
                registerPostProcessor(parserContext, builder, TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME);
            }
        }

        // bean "org.springframework.context.annotation.internalScheduledAnnotationProcessor" 已经存在
        if (registry.containsBeanDefinition(TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            // ... 代码省略
        }
        else {
            // 使用类 "org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor"
            // 来配置bean "org.springframework.context.annotation.internalScheduledAnnotationProcessor"
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
                    "org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor");
            builder.getRawBeanDefinition().setSource(source);
            // scheduler属性
            String scheduler = element.getAttribute("scheduler");
            if (StringUtils.hasText(scheduler)) {
                builder.addPropertyReference("scheduler", scheduler);
            }
            // 注册组件到registry与上下文
            registerPostProcessor(parserContext, builder, TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME);
        }

        // ... 代码省略

        return null;
    }

    // 使用aspectj来执行异步任务
    private void registerAsyncExecutionAspect(Element element, ParserContext parserContext) {
        // bean "org.springframework.scheduling.config.internalAsyncExecutionAspect" 不存在
        if (!parserContext.getRegistry().containsBeanDefinition(TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)) {
            // 使用类 "org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect"
            // 来配置bean "org.springframework.scheduling.config.internalAsyncExecutionAspect"
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ASYNC_EXECUTION_ASPECT_CLASS_NAME);
            // 使用FactoryMethod来初始化bean
            builder.setFactoryMethod("aspectOf");
            // executor属性
            String executor = element.getAttribute("executor");
            if (StringUtils.hasText(executor)) {
                builder.addPropertyReference("executor", executor);
            }
            // exception-handler属性
            String exceptionHandler = element.getAttribute("exception-handler");
            if (StringUtils.hasText(exceptionHandler)) {
                builder.addPropertyReference("exceptionHandler", exceptionHandler);
            }
            // 注册bean
            parserContext.registerBeanComponent(new BeanComponentDefinition(builder.getBeanDefinition(),
                    TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME));
        }
    }
}

4.2. task:executor

ExecutorBeanDefinitionParser
的主要功能是解析元素,用于配置任务执行器

public class ExecutorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    @Override
    protected String getBeanClassName(Element element) {
        // 使用这个类来实现bean
        return "org.springframework.scheduling.config.TaskExecutorFactoryBean";
    }

    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        // keep-alive属性
        String keepAliveSeconds = element.getAttribute("keep-alive");
        if (StringUtils.hasText(keepAliveSeconds)) {
            builder.addPropertyValue("keepAliveSeconds", keepAliveSeconds);
        }
        // queue-capacity属性
        String queueCapacity = element.getAttribute("queue-capacity");
        if (StringUtils.hasText(queueCapacity)) {
            builder.addPropertyValue("queueCapacity", queueCapacity);
        }
        // 配置策略
        configureRejectionPolicy(element, builder);
        // pool-size属性
        String poolSize = element.getAttribute("pool-size");
        if (StringUtils.hasText(poolSize)) {
            builder.addPropertyValue("poolSize", poolSize);
        }
    }

    // 配置策略
    private void configureRejectionPolicy(Element element, BeanDefinitionBuilder builder) {
        // rejection-policy属性
        String rejectionPolicy = element.getAttribute("rejection-policy");
        if (!StringUtils.hasText(rejectionPolicy)) {
            return;
        }
        String prefix = "java.util.concurrent.ThreadPoolExecutor.";
        String policyClassName;
        if (rejectionPolicy.equals("ABORT")) {
            policyClassName = prefix + "AbortPolicy";
        }
        else if (rejectionPolicy.equals("CALLER_RUNS")) {
            policyClassName = prefix + "CallerRunsPolicy";
        }
        else if (rejectionPolicy.equals("DISCARD")) {
            policyClassName = prefix + "DiscardPolicy";
        }
        else if (rejectionPolicy.equals("DISCARD_OLDEST")) {
            policyClassName = prefix + "DiscardOldestPolicy";
        }
        else {
            policyClassName = rejectionPolicy;
        }
        builder.addPropertyValue("rejectedExecutionHandler", new RootBeanDefinition(policyClassName));
    }

}

4.3. task:scheduled-tasks

ScheduledTasksBeanDefinitionParser
的主要功能是解析元素,执行定时器任务

public class ScheduledTasksBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    @Override
    protected String getBeanClassName(Element element) {
        // 使用这个类来实现bean
        return "org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar";
    }

    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        // cron任务
        ManagedList cronTaskList = new ManagedList<>();
        // 固定延迟任务
        ManagedList fixedDelayTaskList = new ManagedList<>();
        // 固定频率任务
        ManagedList fixedRateTaskList = new ManagedList<>();
        // 触发任务
        ManagedList triggerTaskList = new ManagedList<>();

        // 遍历子元素
        NodeList childNodes = element.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node child = childNodes.item(i);

            Element taskElement = (Element) child;
            // ref属性
            String ref = taskElement.getAttribute("ref");
            // method属性
            String method = taskElement.getAttribute("method");

            // ... 代码省略

            // cron属性
            String cronAttribute = taskElement.getAttribute("cron");
            // fixed-delay属性
            String fixedDelayAttribute = taskElement.getAttribute("fixed-delay");
            // fixed-rate属性
            String fixedRateAttribute = taskElement.getAttribute("fixed-rate");
            // trigger属性
            String triggerAttribute = taskElement.getAttribute("trigger");
            // initial-delay属性
            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);

            // ... 代码省略

            // 使用类 "org.springframework.scheduling.support.ScheduledMethodRunnable"
            // 实例化定时器bean
            String runnableName =
                    runnableReference(ref, method, taskElement, parserContext).getBeanName();

            if (hasFixedDelayAttribute) {
                // 使用类 "org.springframework.scheduling.config.IntervalTask"
                // 实例化固定延迟执行器bean
                fixedDelayTaskList.add(intervalTaskReference(runnableName,
                        initialDelayAttribute, fixedDelayAttribute, taskElement, parserContext));
            }
            if (hasFixedRateAttribute) {
                // 使用类 "org.springframework.scheduling.config.IntervalTask"
                // 实例化固定频率执行器bean
                fixedRateTaskList.add(intervalTaskReference(runnableName,
                        initialDelayAttribute, fixedRateAttribute, taskElement, parserContext));
            }
            if (hasCronAttribute) {
                // 使用类 "org.springframework.scheduling.config.CronTask"
                // 实例化cron执行器bean
                cronTaskList.add(cronTaskReference(runnableName, cronAttribute,
                        taskElement, parserContext));
            }
            if (hasTriggerAttribute) {
                // 使用类 "org.springframework.scheduling.config.TriggerTask"
                // 实例化触发执行器bean
                String triggerName = new RuntimeBeanReference(triggerAttribute).getBeanName();
                triggerTaskList.add(triggerTaskReference(runnableName, triggerName,
                        taskElement, parserContext));
            }
        }
        // scheduler属性
        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);
    }
}

4.4. task:scheduler

SchedulerBeanDefinitionParser
的主要功能是解析元素,配置调度线程池

public class SchedulerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    @Override
    protected String getBeanClassName(Element element) {
        // 使用这个类来实现bean
        return "org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler";
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        // pool-size属性
        String poolSize = element.getAttribute("pool-size");
        if (StringUtils.hasText(poolSize)) {
            builder.addPropertyValue("poolSize", poolSize);
        }
    }
}

5. CacheNamespaceHandler

public class CacheNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenCacheBeanDefinitionParser());
        registerBeanDefinitionParser("advice", new CacheAdviceParser());
    }
}

5.1. cache:annotation-driven

AnnotationDrivenCacheBeanDefinitionParser
的主要功能是解析元素,支持注解注 @Cacheable@CacheEvict@CacheUpdate

class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser {
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // mode属性
        String mode = element.getAttribute("mode");
        // 使用aspectj来执行
        if ("aspectj".equals(mode)) {
            registerCacheAspect(element, parserContext);
        }
        // 使用内置的功能来执行
        else {
            registerCacheAdvisor(element, parserContext);
        }

        return null;
    }

    // 使用aspectj来执行
    private void registerCacheAspect(Element element, ParserContext parserContext) {
        SpringCachingConfigurer.registerCacheAspect(element, parserContext);
    }

    // 使用内置的功能来执行
    private void registerCacheAdvisor(Element element, ParserContext parserContext) {
        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
        SpringCachingConfigurer.registerCacheAdvisor(element, parserContext);
    }

    // 解析cache-resolver属性
    private static void parseCacheResolution(Element element, BeanDefinition def, boolean setBoth) {
        String name = element.getAttribute("cache-resolver");
        boolean hasText = StringUtils.hasText(name);
        if (hasText) {
            def.getPropertyValues().add("cacheResolver", new RuntimeBeanReference(name.trim()));
        }
        if (!hasText || setBoth) {
            def.getPropertyValues().add("cacheManager",
                    new RuntimeBeanReference(CacheNamespaceHandler.extractCacheManager(element)));
        }
    }
}

内部类 JCacheCachingConfigurer

private static class JCacheCachingConfigurer {
    // 使用内置的功能来执行
    private static void registerCacheAdvisor(Element element, ParserContext parserContext) {
        // bean "org.springframework.cache.config.internalJCacheAdvisor" 不存在
        if (!parserContext.getRegistry().containsBeanDefinition(CacheManagementConfigUtils.JCACHE_ADVISOR_BEAN_NAME)) {
            Object source = parserContext.extractSource(element);

            // 创建一个JCache执行的bean
            BeanDefinition sourceDef = createJCacheOperationSourceBeanDefinition(element, source);
            // 获取bean名字
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

            // 使用 "org.springframework.cache.jcache.interceptor.JCacheInterceptor"
            // 创建CacheInterceptor的bean定义
            RootBeanDefinition interceptorDef =
                    new RootBeanDefinition("org.springframework.cache.jcache.interceptor.JCacheInterceptor");

            // ... 代码省略

            // 获取bean名字
            String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

            // 使用 "org.springframework.cache.jcache.interceptor.BeanFactoryJCacheOperationSourceAdvisor"
            // 创建CacheAdvisor定义
            RootBeanDefinition advisorDef = new RootBeanDefinition(
                    "org.springframework.cache.jcache.interceptor.BeanFactoryJCacheOperationSourceAdvisor");

            // ... 代码省略

            // 注册bean "org.springframework.cache.config.internalJCacheAdvisor"
            parserContext.getRegistry().registerBeanDefinition(CacheManagementConfigUtils.JCACHE_ADVISOR_BEAN_NAME, advisorDef);

            // 注册复合bean sourceDef+interceptorDef+advisorDef
            CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
            compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
            compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
            compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, CacheManagementConfigUtils.JCACHE_ADVISOR_BEAN_NAME));
            parserContext.registerComponent(compositeDef);
        }
    }

    // 使用aspectj来执行
    private static void registerCacheAspect(Element element, ParserContext parserContext) {
        // bean "org.springframework.cache.config.internalJCacheAspect" 不存在
        if (!parserContext.getRegistry().containsBeanDefinition(CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME)) {
            Object eleSource = parserContext.extractSource(element);
            RootBeanDefinition def = new RootBeanDefinition();

            // 使用 "org.springframework.cache.aspectj.JCacheCacheAspect"
            // 来创建bean
            def.setBeanClassName(JCACHE_ASPECT_CLASS_NAME);
            // 使用FactoryMethod来初始化bean
            def.setFactoryMethodName("aspectOf");
            // 创建一个JCache执行的bean
            BeanDefinition sourceDef = createJCacheOperationSourceBeanDefinition(element, eleSource);
            String sourceName =
                    parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

            // 注册bean "org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource"
            parserContext.registerBeanComponent(new BeanComponentDefinition(sourceDef, sourceName));
            // 注册bean "org.springframework.cache.config.internalJCacheAspect"
            parserContext.registerBeanComponent(new BeanComponentDefinition(def, CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME));
        }
    }

    // 创建一个JCache执行的bean
    private static RootBeanDefinition createJCacheOperationSourceBeanDefinition(Element element, @Nullable Object eleSource) {
        // 使用 "org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource""
        // 来创建bean
        RootBeanDefinition sourceDef =
                new RootBeanDefinition("org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource");

        // ... 代码省略

        // 解析cache-resolver属性
        CacheNamespaceHandler.parseKeyGenerator(element, sourceDef);
        return sourceDef;
    }
}

5.2. cache:advice

CacheAdviceParser
的主要功能是解析元素,配置缓存

class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
    @Override
    protected Class getBeanClass(Element element) {
        // 使用这个类来实现bean
        return CacheInterceptor.class;
    }

    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        // cache-manager属性
        builder.addPropertyReference("cacheManager", CacheNamespaceHandler.extractCacheManager(element));

        // caching元素
        List cacheDefs = DomUtils.getChildElementsByTagName(element, DEFS_ELEMENT);
        // 有caching元素
        if (!cacheDefs.isEmpty()) {
            // 把caching元素转化成bean
            List attributeSourceDefinitions = parseDefinitionsSources(cacheDefs, parserContext);
            builder.addPropertyValue("cacheOperationSources", attributeSourceDefinitions);
        }
        else {
            // 没有caching元素,用 "org.springframework.cache.annotation.AnnotationCacheOperationSource"
            // 创建一个默认的bean
            builder.addPropertyValue("cacheOperationSources",
                    new RootBeanDefinition("org.springframework.cache.annotation.AnnotationCacheOperationSource"));
        }
    }

    // 把caching元素转化成bean
    private List parseDefinitionsSources(List definitions, ParserContext parserContext) {
        ManagedList defs = new ManagedList<>(definitions.size());

        // 遍历
        for (Element element : definitions) {
            defs.add(parseDefinitionSource(element, parserContext));
        }

        return defs;
    }

    // 把caching元素转化成bean
    private RootBeanDefinition parseDefinitionSource(Element definition, ParserContext parserContext) {
        // ... 代码省略
    }
}

6. MvcNamespaceHandler

public class MvcNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
        registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
        registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
        registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
        registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
        registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
        registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
        registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
        registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
    }
}

mvc 命名空间的处理器内容较多,这里只解析第一个 mvc:annotation-driven,其他的有兴趣可以自行探索

AnnotationDrivenBeanDefinitionParser
的主要功能是解析元素,启用注解驱动,通过context:component-scan标签的配置,自动扫描
@Component,@Controller,@Service,@Repository等注解标记的组件注册到工厂中,来处理请求

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    @Override
    public BeanDefinition parse(Element element, ParserContext context) {
        // 元素元信息
        Object source = context.extractSource(element);
        XmlReaderContext readerContext = context.getReaderContext();

        // ... 代码省略

        // 请求映射处理器bean
        RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);

        // ... 代码省略

        // enable-matrix-variables属性
        if (element.hasAttribute("enable-matrix-variables")) {
            boolean enableMatrixVariables = Boolean.parseBoolean(element.getAttribute("enable-matrix-variables"));
            handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
        }

        // 配置路径映射
        configurePathMatchingProperties(handlerMappingDef, element, context);
        // 注册RequestMappingHandlerMapping.class bean
        readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);

        // ... 代码省略

        // 获取数据转换服务
        RuntimeBeanReference conversionService = getConversionService(element, source, context);
        // 获取验证器
        RuntimeBeanReference validator = getValidator(element, source, context);
        // 获取文本解析器
        RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);

        // 注册ConfigurableWebBindingInitializer.class bean
        RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);

        // ... 代码省略

        // 载入conversionService、validator、messageCodesResolver
        bindingDef.getPropertyValues().add("conversionService", conversionService);
        bindingDef.getPropertyValues().add("validator", validator);
        bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);

        // 配置消息转换器
        ManagedList messageConverters = getMessageConverters(element, source, context);
        // argument-resolvers子元素配置的自定义参数解析器
        ManagedList argumentResolvers = getArgumentResolvers(element, context);
        // return-value-handlers子元素配置的自定义响应解析器
        ManagedList returnValueHandlers = getReturnValueHandlers(element, context);
        // async-support子元素配置的异步任务超时时间
        String asyncTimeout = getAsyncTimeout(element);
        // async-support子元素配置的异步任务执行器
        RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
        // async-support子元素配置的callable-interceptors请求拦截器
        ManagedList callableInterceptors = getInterceptors(element, source, context, "callable-interceptors");
        // async-support子元素配置的deferred-result-interceptors响应拦截器
        ManagedList deferredResultInterceptors = getInterceptors(element, source, context, "deferred-result-interceptors");

        // 注册RequestMappingHandlerAdapter.class bean
        RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
        // 载入contentNegotiationManager、bindingDef、messageConverters
        handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
        handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
        handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
        // 载入jackson请求处理
        addRequestBodyAdvice(handlerAdapterDef);
        // 载入jackson响应处理
        addResponseBodyAdvice(handlerAdapterDef);

        // ignore-default-model-on-redirect属性
        if (element.hasAttribute("ignore-default-model-on-redirect")) {
            Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignore-default-model-on-redirect"));
            handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
        }
        if (argumentResolvers != null) {
            handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
        }
        if (returnValueHandlers != null) {
            handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
        }
        if (asyncTimeout != null) {
            handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
        }
        if (asyncExecutor != null) {
            handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
        }

        handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
        handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);

        // 注册RequestMappingHandlerAdapter.class bean
        readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);

        // 注册CompositeUriComponentsContributorFactoryBean.class bean
        RootBeanDefinition uriContributorDef =
                new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
        uriContributorDef.setSource(source);
        uriContributorDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
        uriContributorDef.getPropertyValues().addPropertyValue("conversionService", conversionService);

        // 注册mvcUriComponentsContributor bean
        String uriContributorName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
        readerContext.getRegistry().registerBeanDefinition(uriContributorName, uriContributorDef);

        // 注册ConversionServiceExposingInterceptor.class bean
        RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
        csInterceptorDef.setSource(source);
        csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);

        // 注册MappedInterceptor.class bean
        RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);

        // ... 代码省略

        // 注册ExceptionHandlerExceptionResolver.class bean
        RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);

        // ... 代码省略

        // 注册ResponseStatusExceptionResolver.class bean
        RootBeanDefinition statusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);

        // ... 代码省略

        // 注册DefaultHandlerExceptionResolver.class bean
        RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);

        // ... 代码省略

        // 注册一系列bean
        context.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
        context.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
        context.registerComponent(new BeanComponentDefinition(uriContributorDef, uriContributorName));
        context.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, mappedInterceptorName));
        context.registerComponent(new BeanComponentDefinition(methodExceptionResolver, methodExResolverName));
        context.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
        context.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));

        // ... 代码省略

        context.popAndRegisterContainingComponent();

        return null;
    }
}
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    // 配置路径映射
    private void configurePathMatchingProperties(
            RootBeanDefinition handlerMappingDef, Element element, ParserContext context) {
        // 获取path-matching子元素
        Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
        if (pathMatchingElement != null) {
            Object source = context.extractSource(element);

            // suffix-pattern属性
            if (pathMatchingElement.hasAttribute("suffix-pattern")) {
                Boolean useSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("suffix-pattern"));
                handlerMappingDef.getPropertyValues().add("useSuffixPatternMatch", useSuffixPatternMatch);
            }
            // trailing-slash属性
            if (pathMatchingElement.hasAttribute("trailing-slash")) {
                Boolean useTrailingSlashMatch = Boolean.valueOf(pathMatchingElement.getAttribute("trailing-slash"));
                handlerMappingDef.getPropertyValues().add("useTrailingSlashMatch", useTrailingSlashMatch);
            }
            // registered-suffixes-only属性
            if (pathMatchingElement.hasAttribute("registered-suffixes-only")) {
                Boolean useRegisteredSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("registered-suffixes-only"));
                handlerMappingDef.getPropertyValues().add("useRegisteredSuffixPatternMatch", useRegisteredSuffixPatternMatch);
            }

            RuntimeBeanReference pathHelperRef = null;
            // path-helper属性
            if (pathMatchingElement.hasAttribute("path-helper")) {
                pathHelperRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-helper"));
            }
            pathHelperRef = MvcNamespaceUtils.registerUrlPathHelper(pathHelperRef, context, source);
            handlerMappingDef.getPropertyValues().add("urlPathHelper", pathHelperRef);

            RuntimeBeanReference pathMatcherRef = null;
            // path-matcher属性
            if (pathMatchingElement.hasAttribute("path-matcher")) {
                pathMatcherRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-matcher"));
            }
            pathMatcherRef = MvcNamespaceUtils.registerPathMatcher(pathMatcherRef, context, source);
            handlerMappingDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
        }
    }

    // 获取数据转换服务
    private RuntimeBeanReference getConversionService(Element element, @Nullable Object source, ParserContext context) {
        RuntimeBeanReference conversionServiceRef;
        // 有配置conversion-service属性
        if (element.hasAttribute("conversion-service")) {
            conversionServiceRef = new RuntimeBeanReference(element.getAttribute("conversion-service"));
        }
        else {
            // 没有就用FormattingConversionServiceFactoryBean创建一个默认的
            RootBeanDefinition conversionDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);

            // ... 代码省略

            conversionServiceRef = new RuntimeBeanReference(conversionName);
        }
        return conversionServiceRef;
    }

    // 获取验证器
    private RuntimeBeanReference getValidator(Element element, @Nullable Object source, ParserContext context) {
        // 有配置validator属性
        if (element.hasAttribute("validator")) {
            return new RuntimeBeanReference(element.getAttribute("validator"));
        }
        else if (javaxValidationPresent) {
            // 没有就用OptionalValidatorFactoryBean创建一个默认的
            RootBeanDefinition validatorDef = new RootBeanDefinition(
                    "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean");

            // ... 代码省略

            return new RuntimeBeanReference(validatorName);
        }
        else {
            return null;
        }
    }

    // 获取文本解析器
    private RuntimeBeanReference getMessageCodesResolver(Element element) {
        // 有配置message-codes-resolver属性
        if (element.hasAttribute("message-codes-resolver")) {
            return new RuntimeBeanReference(element.getAttribute("message-codes-resolver"));
        }
        else {
            return null;
        }
    }
}
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    // 配置消息转换器
    private ManagedList getMessageConverters(Element element, @Nullable Object source, ParserContext context) {
        // message-converters子元素
        Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
        // 结果集
        ManagedList messageConverters = new ManagedList<>();

        // 有message-converters子元素
        if (convertersElement != null) {
            // 把bean、ref子元素转换为bean,加入结果集
            for (Element beanElement : DomUtils.getChildElementsByTagName(convertersElement, "bean", "ref")) {
                Object object = context.getDelegate().parsePropertySubElement(beanElement, null);
                messageConverters.add(object);
            }
        }

        // 有message-converters子元素,但有register-defaults属性
        if (convertersElement == null || Boolean.parseBoolean(convertersElement.getAttribute("register-defaults"))) {
            // 添加ByteArrayHttpMessageConverter.class bean到结果集
            // 字节数组转换器
            messageConverters.add(createConverterDefinition(ByteArrayHttpMessageConverter.class, source));

            // 添加StringHttpMessageConverter.class bean到结果集
            // 字符转换器
            RootBeanDefinition stringConverterDef = createConverterDefinition(StringHttpMessageConverter.class, source);
            stringConverterDef.getPropertyValues().add("writeAcceptCharset", false);
            messageConverters.add(stringConverterDef);

            // 添加ResourceHttpMessageConverter.class bean到结果集
            // 资源转换器
            messageConverters.add(createConverterDefinition(ResourceHttpMessageConverter.class, source));
            // 添加ResourceRegionHttpMessageConverter.class bean到结果集
            // 资源区域转换器
            messageConverters.add(createConverterDefinition(ResourceRegionHttpMessageConverter.class, source));
            // 添加SourceHttpMessageConverter.class bean到结果集
            // javax.xml.transform.Source转换器
            messageConverters.add(createConverterDefinition(SourceHttpMessageConverter.class, source));
            // 添加AllEncompassingFormHttpMessageConverter.class bean到结果集
            // form-data转换器
            messageConverters.add(createConverterDefinition(AllEncompassingFormHttpMessageConverter.class, source));

            // ... 代码省略

            if (jackson2XmlPresent) {
                // 添加jackson2Xml转换器
            }

            // ... 代码省略

            if (jackson2Present) {
                // 添加jackson2转换器
            }
            else if (gsonPresent) {
                // 添加gson转换器
            }

            // ... 代码省略
        }
        return messageConverters;
    }
} 
 

后续

更多博客,查看 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证

你可能感兴趣的:(后端javaspring)