私はSpring 3を使用して準大規模なアプリケーションに取り組んでおり、一度に何百人ものユーザーを投入するとパフォーマンスの問題が発生します. Spring の AOP プロキシを使用していくつかのリクエスト スコープ Bean を使用しています。これらの Bean のいずれかでメソッドを呼び出すたびに、CGLIB インターセプターが呼び出され、AbstractBeanFactory.getBean() が呼び出され、add() が呼び出されることがわかります。既存の Spring Bean の同期セット。この add() は同期されているため、同じリストへの追加を待機している何千もの呼び出しがあると、サーバーが効果的にロックされます。
リクエストスコープのBeanを使用してこれを回避する方法はありますか? Bean がインターフェイスを実装している場合は CGLIB が使用されないことを Spring のドキュメントで読みました (http://static.springsource.org/spring/docs/2.0.0/reference/aop.html#d0e9015) が、私のリクエストはスコープ Bean です。すべてが1つ(実際には同じもの)を実装しており、それはまだ起こっています。また、Bean のフィールドの一部は特定のリクエストに対してアプリの一部で計算され、SpEL を使用して同じリクエスト中にアプリの別の部分で値を取得するため、Bean をリクエスト スコープにする必要があります。Bean プロトタイプをスコープ化した場合、SpEL を使用して 2 回目に取得したときに新しいオブジェクトが得られると思います。
これは私の問題を示すコードサンプルです。私が問題を抱えている正確な場所を説明するコメントについては、最後の 2 行を参照してください。
<!-- Spring config -->
<bean name="someBean" class="some.custom.class.SomeClass" scope="request">
<property name="property1" value="value1"/>
<property name="property2" value="value2"/>
<aop:scoped-proxy/>
</bean>
<bean name="executingClass" class="some.other.custom.class.ExecutingClass" scope="singleton">
<property name="myBean" ref="someBean" />
</bean>
public Interface SomeInterface {
public String getProperty1();
public void setProperty1(String property);
public String getProperty2();
public void setProperty2(String property);
}
public class SomeClass implements SomeInterface {
private String property1;
private String property2;
public String getProperty1() { return propery1; }
public void setProperty1(String property) { property1=property;}
public String getProperty2() { return propery2; }
public void setProperty2(String property) { property2=property;}
}
public class ExecutingClass {
private SomeInterface myBean;
public void execute() {
String property = myBean.getProperty1(); // CGLIB interceptor is invoked here, registering myBean as a bean
String otherProperty = myBean.getProperty2(); // CGLIB interceptor is invoked here too! Seems like this is unnecessary. And it's killing my app.
}
}
私のアイデアは次のいずれかです。
- Bean で行われたすべてのメソッド呼び出しをプロキシせずに、スコープ指定された Spring Bean リクエストを作成できますか? そして、すべてのメソッドを「最終」としてマークせずに?
また...
- Spring の Bean ファクトリをオーバーライドして、AbstractBeanFactory.getBean() を呼び出す前に Bean がキャッシュされているかどうかを確認する Bean キャッシュを実装できますか? もしそうなら、カスタム Bean ファクトリーを使用するように Spring をどこで構成すればよいでしょうか?