2009-06-07 4 views
2

私たちのプロジェクトは簡単な拡張性を提供するSpring IoCをベースにしています。つまり、Springのxmlを追加する拡張機能(またはプラグイン)設定ファイル+新しいコード。異なるスプリングコンフィグレーションファイルからロードされたBeanを区別する

問題は、別のXMLファイルから読み込まれたBeanを何とか区別しなければならないことです。

例:2つの拡張子(AとBと呼ぶ)は、2つの追加のスプリングファイルA.xmlとB.xmlをインストールしました。これらのファイルは、どちらも同じJavaクラスのBeanを定義します。フレームワークは、このクラスのすべてのBeanを(オートワイヤリングを使用して)いくつかのファクトリにロードし、その後、このBeanのリストを特定のアルゴリズムで使用します。しかし、Beanがどの拡張子で定義されているかを知ることができます。

もちろん、Beanに必要なプロパティ(たとえば、拡張子の名前やコード)を追加して、拡張開発者がすべてのBean定義に対してそれを埋めなければならない場合がありますが、これはエラーが発生しやすくなります。特定の拡張のすべてのBeanに対して同じですが、Beanごとに満たされます。私はあまり冗長ではありませんより洗練されたソリューションを探しています。

ありがとうございました。

答えて

1

それぞれの拡張機能は、独自のアプリケーションコンテキスト内で定義する必要があります。これらの各コンテキストは、アプリケーションの「コア」となる単一の親コンテキストを共有します。

このshoulkdはどのBeanが何から来たのかを簡単に知る方法を提供します。なぜなら、Beanを取得するために各コンテキストを調べなければならないからです。また、独自のコンテキスト内で各拡張を分離することで、Beanの衝突の可能性を減らすことができます。

+0

ありがとうございました。それは興味深い考えのように聞こえる。しかし、どのように私は各設定ファイルの新しいコンテキストを割り当てるのですか? – Stas

+0

現時点でどのように拡張設定ファイルを特定して読み込みますか? – skaffman

+0

現在、私は正規表現を使って設定ファイルをロードしています。例えば、私はproduct - * - config.xmlファイルをロードしています。そのため、拡張機能がproduct-myextension-config.xmlファイルをデプロイするとロードされます。あなたの提案されたアプローチを使用しているようです。命名規則を厳しくし、各拡張モジュールの設定ファイル名を別々に事前定義して、別のコンテキストでそれらを読み込むことができるようにする必要があります。妥当な音です。私はそれを試してみます、ありがとう! – Stas

1

各拡張機能を別々のアプリケーションコンテキストで設定します。各アプリケーションコンテキストでは、BeanPostProcessorを定義し、アプリケーションコンテキストが定義するすべてのBeanを、Beanをアプリケーションコンテキストにマップするレジストリに保存します。

各拡張アプリケーションコンテキストの親となるアプリケーションコンテキストを設定します。この設定ファイルで、Bean名をアプリケーションコンテキスト識別子にマップするBeanを定義します。

<!-- parent.xml --> 
<beans> 

    <bean 
     id="beanNameToApplicationContextIdMap" 
     class="java.util.HashMap"/> 

</beans> 

拡張アプリケーションコンテキストコンフィギュレーションファイルは、BeanPostProcessorインタフェースを実装するカスタムクラスであるBeanNameToApplicationContextIdMapInserterのインスタンスを定義します。 applicationContextIdプロパティは、アプリケーションコンテキストを識別する文字列に構成されます。 mapプロパティは、親アプリケーションコンテキストで定義されたマップを更新するようにインスタンスを構成します。

<!-- alpha.xml --> 
<beans> 

    <bean class="com.example.BeanNameToApplicationContextIdMapInserter"> 
    <property name="applicationContextId" value="alpha"/> 
    <property name="map" ref="beanNameToApplicationContextIdMap"/> 
    </bean> 

    <bean id="alphaService" class="..."> 
    </bean> 

</beans> 

BeanNameToApplicationContextIdMapInserterソースコード:

public class BeanNameToApplicationContextIdMapInserter implements BeanPostProcessor { 

    private String applicationContextId; 
    private HashMap<String, String> map; 

    public void setApplicationContextId(String id) { 
     this.applicationContextId = id; 
    } 

    public void setMap(HashMap<String, String> map) { 
     this.map = map; 
    } 

    public Object postProcessBeforeInitialization(Object bean, String beanName) 
     throws BeansException 
    { 
     return bean; 
    } 

    public Object postProcessAfterInitialization(Object bean, String beanName) 
     throws BeansException 
    { 
     map.put(beanName, applicationContextId); 
     return bean; 
    } 
} 

あなたは親アプリケーションのコンテキストおよび各拡張アプリケーションコンテキストを設定するためにSingletonBeanFactoryLocatorを使用することができます。

<!-- beanRefFactory.xml --> 
<beans> 

    <bean 
     id="parentApplicationContext" 
     class="org.springframework.context.support.ClassPathXmlApplicationContext"> 
    <constructor-arg> 
     <value>parent.xml</value> 
    </constructor-arg> 
    </bean> 

    <bean 
     id="alphaApplicationContext" 
     class="org.springframework.context.support.ClassPathXmlApplicationContext"> 
    <constructor-arg> 
     <value>alpha.xml</value> 
    </constructor-arg> 
    <constructor-arg> 
     <ref bean="parentApplicationContext"/> 
    </constructor-arg> 
    </bean> 

    <bean 
     id="bravoApplicationContext" 
     class="org.springframework.context.support.ClassPathXmlApplicationContext"> 
    <constructor-arg> 
     <value>bravo.xml</value> 
    </constructor-arg> 
    <constructor-arg> 
     <ref bean="parentApplicationContext"/> 
    </constructor-arg> 
    </bean> 

</beans> 

ここで、Beanをアプリケーションコンテキストマップに読み込むコードの例を示します。

public class Main { 

    private static ApplicationContext getApplicationContext(String name) { 
     BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance(); 
     BeanFactoryReference bfr = bfl.useBeanFactory(name); 
     return (ApplicationContext) bfr.getFactory(); 
    } 

    public static void main(String[] args) { 
     ApplicationContext parentApplicationContext = 
       getApplicationContext("parentApplicationContext"); 
     HashMap<String, String> map = (HashMap<String, String>) 
       parentApplicationContext.getBean("beanNameToApplicationContextIdMap"); 

     System.out.println(map.get("alphaService")); 

     System.out.println(map.get("bravoService")); 
    } 
} 
+0

おかげさまで、面白いと思うかもしれませんが(上記の別の答えと同様です):提案されたアプローチについて少し考えた後、私はautowiring機能の恩恵を受けることはできません - 工場コアアプリケーションのコンテキストでは、子アプリケーションのコンテキストでBeanの定義をautowireしません。これは私にとって非常に不便です:-( – Stas

関連する問題