何千ものクラスから結果を返すことができる複数のサービスがあります。
各 CXF サービスにはプライベートでほぼ同一の JAXB コンテキストが含まれているため、大量のメモリが浪費されます。
自分で JAXB コンテキストを作成し、それをサービス間で共有する方法はありますか?
1 に答える
これを解決する 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 の最後の行に等号を追加できなかったので、等号を関連する記号に置き換えてください。