LoginSignup
1
1

More than 5 years have passed since last update.

Spring Framework Bean定義のXML:カスタムタグ

Posted at

はじめに

Spring FrameworkのドキュメントでBean定義のXML要素"<util:list>"の例がある。
https://docs.spring.io/spring/docs/5.0.x/spring-framework-reference/core.html#xsd-schemas-util-list

<!-- creates a java.util.List instance with the supplied values -->
<util:list id="emails">
    <value>pechorin@hero.org</value>
    <value>raskolnikov@slums.org</value>
    <value>stavrogin@gov.org</value>
    <value>porfiry@gov.org</value>
</util:list>

このコードの意味は下と同じ。

<!-- creates a java.util.List instance with values loaded from the supplied 'sourceList' -->
<bean id="emails" class="org.springframework.beans.factory.config.ListFactoryBean">
    <property name="sourceList">
        <list>
            <value>pechorin@hero.org</value>
            <value>raskolnikov@slums.org</value>
            <value>stavrogin@gov.org</value>
            <value>porfiry@gov.org</value>
        </list>
    </property>
</bean>

どんな魔法をかけるのかちょっと興味があるので、ソースコードに探し始めた。

魔法の真実

まず、Eclipseでインタフェースorg.springframework.beans.factory.xmlBean.DefinitionParserを実装するクラスをさがす。いっばいのクラスでてきた。その中org.springframework.beans.factory.xml.UtilNamespaceHandler(ジャバアーカイブspring-beans-3.2.3.RELEASE.jar)があやしい。ソースコードを読み、

org.springframework.beans.factory.xml.UtilNamespaceHandler
...
    public void init() {
        registerBeanDefinitionParser("constant", new ConstantBeanDefinitionParser());
        registerBeanDefinitionParser("property-path", new PropertyPathBeanDefinitionParser());
        registerBeanDefinitionParser("list", new ListBeanDefinitionParser());
        registerBeanDefinitionParser("set", new SetBeanDefinitionParser());
        registerBeanDefinitionParser("map", new MapBeanDefinitionParser());
        registerBeanDefinitionParser("properties", new PropertiesBeanDefinitionParser());
    }
...

XML要素"list"の扱うクラスを見つけるかな。同じのジャバアーカイブの中、ファイル"/META-INF/spring.handlers"を確認してみると、

http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler

ビンゴ!名前空間"util"の要素は本当にクラスorg.springframework.beans.factory.xml.UtilNamespaceHandlerに扱う。メソッドinit()に戻りましょ。XML要素"list"はクラスListBeanDefinitionParser(org.springframework.beans.factory.xml.UtilNamespaceHandlerのインナークラス)に扱う。

org.springframework.beans.factory.xml.UtilNamespaceHandler
...
    private static class ListBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

        @Override
        protected Class getBeanClass(Element element) {
            return ListFactoryBean.class;
        }

        @Override
        protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
            String listClass = element.getAttribute("list-class");
            List parsedList = parserContext.getDelegate().parseListElement(element, builder.getRawBeanDefinition());
            builder.addPropertyValue("sourceList", parsedList);
            if (StringUtils.hasText(listClass)) {
                builder.addPropertyValue("targetListClass", listClass);
            }
            String scope = element.getAttribute(SCOPE_ATTRIBUTE);
            if (StringUtils.hasLength(scope)) {
                builder.setScope(scope);
            }
        }
    }
...

メソッドgetBeanClass()はファクトリクラスorg.springframework.beans.factory.config.ListFactoryBeanを設定する。そしてメソッドdoParse()はXML属性と子要素をよむ役目。

参考資料

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1