2011-10-28 9 views
1

私のアプリケーションは、異なる環境で動作することができます。環境ごとにMYデータモデルを構成する必要があります。データモデルはSpring Beanを使用してビルドされています。Springは抽象Beanを非抽象に変換できますか?

私はSpring 3.0.5を使用しているため、条件付きでリソースを読み込むことはできません。 私はこれがあります。

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

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

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

<bean id="Factory" ...> 
<propety name="type"><value>${app.type}</value></property> 
<property> 
<map> 
    <entry key="Temlate1" value-ref="Template1"> 
    <entry key="Temlate2" value-ref="Template1"> 
    <entry key="Temlate3" value-ref="Template1"> 

.................. 

実豆、私は工場で作成します。

<bean id="real" factory="Factory" factory-method="getInstance" 
<constructor-arg>Factory</..... 
............. 
</bean> 

Javaコード:

class Factory { 
private Map<String, Object> templateBeans; 

Object getInstance(String name) { 
    return templateBeans.get(name); 
........... 

それは何らかの方法で抽象テンプレート豆を宣言することは可能ですか?私は記憶に非常に大きな問題があるからです。バージョン3.1より前のSpringでは、別のBeanを条件付きでインスタンス化する別の方法がありますか?私が豆のJavaコードにアクセスすることはできないので、ELだけを使用するとよいでしょう。なぜなら、彼らはサードパーティ製のライブラリからのものだからです。

+0

私が正しく理解していると、インスタンス化されているが使用されていないSpring Beanがあり、これが原因でメモリの問題が発生すると考えられます。そうですか?それらの未使用シングルトンテンプレートBeanがあなたの記憶上の問題を引き起こすものであることを明確に診断しましたか?それとも暗闇の中でのショットですか? –

+0

これらのテンプレートBeanには、別のオブジェクトへの参照が含まれていて、合計で1000個の追加オブジェクトがあります。 – user710818

+1

これらのオブジェクトのそれぞれが10 KBのメモリを消費する場合、それでも10 MBしかありません。それを修正しようとする前に、実際に問題が発生していることを確認してください。 –

答えて

5

私はこれを試していませんが、私はあなたがこれに対してBeanエイリアスを使用できると確信しています。

まず、すべてのテンプレートBeanを遅延時に宣言して、起動時にインスタンス化されないようにします。

<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/> 

は、その後、実際の1を指すように変数と豆のエイリアスを使用します。

property-placeholder location from another property

0

可能であれば、クリーンな解決策は、Factoryを使用せず、異なる環境に異なる設定ファイルを使用することです。すべて同じ '実際の' Beanを定義しますが、実装は異なります。実行時に正しいバージョンをインポートするだけです。テンプレート$ {app.type} .xml。

もう一つの醜い解決策は、テンプレートBeanを遅延待ちBeanにして、それらが動的に作成されるようにすることです。とにかくそれらをインスタンス化するので、工場の地図にそれらを挿入することはできません。代わりにbeanNamesのマップを保存して、Factory ApplicationContextAwareを作成することができます。次に、getInstance()メソッドでapplicationContext.getBean(beanNames.get(...))を返します。

XML設定とSpring JavaConfigを混在させることで、より精巧な解決策が得られます。これにより、Bean定義内のあらゆる種類のロジックが可能になります。

+0

バージョン3.0.5ではこれはできません。可能なのは3.1 – user710818

+0

最初の解決策では、$ {app.type}という変数をビルドタイプで置き換える必要があります。 Mavenプロファイルでは、それはあなたのための解決策ではないと思います。私の2番目の解決策は動作しますが、@ pablojimの答えはさらに優雅です。 – greyfairer

1

これまでにこの問題が発生したため、Springのインポートタグを使用しました。例:

<import resource="file:/location/to/your/config/my_beans.xml"/> 

これにより、アプリケーションwar/jarからSpring XML設定を外部化できます。あなたの状況では、それぞれの環境に別々の外部Spring XML設定を配備する必要がありますが、必要なものを正確にインスタンス化することもできます。

+0

私は変数を使用します。 3.1より前のSpringの問題は、変数がインポート・リソースの後に値を受け取るという問題です。 – user710818

+1

あなたは不動産プレースホルダを使用しているのですか? –

0

<alias name="real" alias="${beanForEnvironment}"/> 

うまく環境ごとにプロパティをロードする方法のためにここに私の答えを参照してください。

Spring 3.1にアップグレードできる場合は、profies

アップグレードがオプションでない場合は、system variables(例:$ {ENV_SYSTEM:dev})を使って設定(プロパティ)を切り替えます。

もう一つの良いSOの一つがあるCommon strategies when defining Spring beans for different environments

例えばあなたにservice-development.xmlで開発豆を持っているとして、それをインポートします。

<import resource="service-${profile}.xml"/> 

-Dprofile=developmentでそれを開始します。 QAにロールバックしたとき:-Dprofile=qa

+0

3.1にアップグレードすることはできません。明らかに3.1では問題はありません。 – user710818

+0

なぜシステム変数を使用できないのですか? "-Dprofile = production"で起動します。 ? [それ以前のバージョンでは2.5以降で動作します] – tolitius

0

怠惰なinitを使用lazy-init="true"しかし、豆はMapで参照されるとインスタンス化される可能性があります。そのため、インスタンスの名前にStringのマップを使用して、コードによって。 context.getBean(MyInterface.class, templates.get(name));

0

tolitiusは、実行時引数がうまくいくことを示唆しています。 -Dyourvar = yourvalueをJavaランタイムに渡すことができ、Springインポートで$ {yourvar}を使用できます。設定されていない場合は、春からのリソースが見つかりませんでした。

スタンドアロンプ​​ログラムの場合:java YourClass -Dyourvar = yourvalue アプリケーションサーバーを使用している場合は、実行時引数も設定できます。サーバのメモリを増やす方法については、サーバのマニュアルを検索してください。場所は、-Xmx設定を設定できるところでした。通常、-Dyourvar定数を設定できる場所です。

関連する問題