10

何千ものクラスから結果を返すことができる複数のサービスがあります。
各 CXF サービスにはプライベートでほぼ同一の JAXB コンテキストが含まれているため、大量のメモリが浪費されます。
自分で JAXB コンテキストを作成し、それをサービス間で共有する方法はありますか?

4

1 に答える 1

3

これを解決する 1 つの方法として、Spring 構成に以下を追加する方法があります。

<bean class="org.apache.cxf.jaxb.JAXBDataBinding" >
    <constructor-arg index="0" value="#{GlobalContextBean.context}"/>
</bean>

値は、グローバル (単一) JAXBContext を保持し、次のメソッドを持つ Bean への単なる参照です。

public javax.xml.bind.JAXBContext getContext() {...}

次のスレッドで詳細 (CXF グルの Daniel Kulp 入力を含む) を確認できます:
Reuse-JAXB-context-in-jaxws

テストした後、現在の JAXBDataBinding を複数のサービスのグローバル インスタンスとして設定しても機能しないことがわかりました。これは、initialize メソッドに "if" ステートメントがあり、最初のサービスによってコンテキストが設定されると返されるためです。
そのため、クラスを拡張し、必要なすべてのサービス クラスとモデル クラスを収集することになりました。すべてのサービスの初期化が終了したら、必要なすべてのクラスを含むグローバル コンテキストを作成し、それをすべてのサービスに返します。
次のクラスを使用できます。
すべての Web サービスが初期化されたら、compileGlobalJAXBContext メソッドを呼び出してグローバル コンテキストを作成します。アプリケーションが必要とし、init が見逃した他のクラスをそこに追加できます。
この Bean で動作するようにサービスを構成することを忘れないでください。

public class GlobalJAXBDataBinding extends JAXBDataBinding
{
private Set<Class<?>> globalContextClasses;
private boolean contextBuilt = false;

public GlobalJAXBDataBinding(Set<Class<?>> classes) {
    globalContextClasses = new HashSet<>(classes);
    globalContextClasses.add(CPUUID.class);
}

public GlobalJAXBDataBinding() {
}

}

public synchronized void initialize(Service service) {
    if (contextBuilt)
        return;
    super.initialize(service);
    globalContextClasses.addAll(getContextClasses());
    super.setContext(null);
}

public void compileGlobalJAXBContext() {
    if (contextBuilt) return;
    setContext(JAXBContext.newInstance(globalContextClasses));
    contextBuilt *equals* true; 
}

何らかの奇妙な理由で、エディターは compileGlobalJAXBContext の最後の行に等号を追加できなかったので、等号を関連する記号に置き換えてください。

于 2012-10-03T07:12:38.777 に答える