1

以下と同等のものを達成できるものはありますか:

<import resource="a.xml">
    <prop name="key" value="a"/>
</import>

<import resource="a.xml">
    <prop name="key" value="b"/>
</import>

リソース a で定義された Bean が 2 つの異なる値を持つプロパティ キーを参照するようにするには? これは、リソース a.xml が表示されるように、インポートで Bean に名前を付けるために使用されることを意図しています。

<bean id="${key}"/>

したがって、アプリケーションには名前が付けられた 2 つの Bean がaありb、同じ定義で異なるインスタンスとして使用できるようになります。プロトタイプのスコープについては知っています。これは意図したものではありません。実際にはプロトタイプではない、相互依存関係で作成された多くのオブジェクトが存在します。現在、a.xml をコピーし、b.xml を作成し、同等のsedコマンドを使用してすべての Bean の名前を変更しています。もっと良い方法があるに違いないと感じています。

4

1 に答える 1

1

PropertyPlaceholderConfigurersはコンテナーごとに機能すると思います。そのため、xmlインポートではこれを実現できません。

The application would have two beans named a and b now available with the same definition but as distinct instances

現在のアプリケーションコンテキストを親アプリケーションコンテキストとして使用して、追加のアプリケーションコンテキスト(たとえば、ClassPathXmlApplicationContext)を手動で作成することを検討する必要があると思います。したがって、many objects created with interdependenciesセットはそれぞれ独自のコンテナに常駐します。

bただし、この場合、 -containerから-beansを参照することはできませんa

更新BeanDefinitionRegistryPostProcessor専用Beanを登録することで、Bean定義を手動で後処理(新しい定義を追加)できます が、この解決策も簡単ではないようです。

OK、これがxmlファイルを手動でインポートする私の大まかな試みです:

免責事項:私は実際には非常に悪いJava ioプログラマーなので、リソース関連のコードを再確認してください:-)

public class CustomXmlImporter implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }

    private Map<String, String> properties;

    public void setProperties(Map<String, String> properties) {
        this.properties = properties;
    }

    public Map<String, String> getProperties() {
        return properties;
    }

    private void readXml(XmlBeanDefinitionReader reader) {
        InputStream inputStream;
        try {
            inputStream = new ClassPathResource(this.classpathXmlLocation).getInputStream();
        } catch (IOException e1) {
            throw new AssertionError();
        }
        try {

            Scanner sc = new Scanner(inputStream);
            try {
                sc.useDelimiter("\\A");
                if (!sc.hasNext())
                    throw new AssertionError();
                String entireXml = sc.next();

                PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${",
                        "}", null, false);
                Properties props = new Properties();
                props.putAll(this.properties);
                String newXml = helper.replacePlaceholders(entireXml, props);
                reader.loadBeanDefinitions(new ByteArrayResource(newXml.getBytes()));

            } finally {
                sc.close();
            }

        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new AssertionError();
            }
        }
    }

    private String classpathXmlLocation;

    public void setClassPathXmlLocation(String classpathXmlLocation) {
        this.classpathXmlLocation = classpathXmlLocation;
    }

    public String getClassPathXmlLocation() {
        return this.classpathXmlLocation;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(
            BeanDefinitionRegistry registry) throws BeansException {
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
        readXml(reader);
    }
}

XML構成:

<bean class="CustomXmlImporter">
    <property name="classPathXmlLocation" value="a.xml" />
    <property name="properties">
        <map>
            <entry key="key" value="a" />
        </map>
    </property>
</bean>
<bean class="CustomXmlImporter">
    <property name="classPathXmlLocation" value="a.xml" />
    <property name="properties">
        <map>
            <entry key="key" value="b" />
        </map>
    </property>
</bean>

このコードは、クラスパスからリソースをロードします。そのようなことをする前に、私はよく考えます、とにかく、あなたはこれを出発点として使うことができます。

于 2012-11-22T13:57:43.337 に答える