現在、JSF 2 と Spring 3 AOP の組み合わせを使用して問題に直面しています。
アプリケーションは、従来の 3 層アーキテクチャ (Web、サービス、データベース) として設計されています。したがって、Spring 管理の JSF-Bean は、ビジネス ロジックを表すサービス Bean を呼び出します。
マネージド Bean は次のようになります。
@Named("startPage")
@Scope("view")
public class ManagedBean implements Serializable {
@Inject
private ServiceBeanA serviceBeanA;
public void someMethod() {
serviceBean.doSomeBusinessLogic();
}
この Bean はビュー スコープであるため、Serializeable を実装し、インスタンス変数 (この場合は ServiceBeanA) も実装します ( JSF バッキング Bean はシリアル化できる必要がありますか?
これまでのところ、すべてが期待どおりに機能しています。
ここで、ビジネス サービスで宣言されたビジネス メソッドの呼び出しをインターセプトしたいと考えています。そこで、いくつかの基本的なロギングを行うアスペクトを作成し、Spring 構成で宣言しました。
<bean id="aspectLogging" class="my.package.AspectLogging" />
<aop:config>
<aop:aspect ref="aspectLogging">
<aop:pointcut id="serviceMethodInvocation" expression="execution(* my.services.ServiceBeanA.doSomeBusinessLogic())" />
<aop:around pointcut-ref="serviceMethodInvocation" method="performLogging" />
</aop:aspect>
</aop:config>
アスペクト:
public class AspectLogging {
public Object performLogging(ProceedingJoinPoint pjp) throws Throwable {
Object toReturn = null;
System.out.println(">>>>"+ pjp.getSignature().toLongString());
toReturn = pjp.proceed();
return toReturn;
}
}
そして今、問題が発生します:
SCHWERWIEGEND: Exiting serializeView - Could not serialize state: org.springframework.aop.aspectj.AspectJPointcutAdvisor
java.io.NotSerializableException: org.springframework.aop.aspectj.AspectJPointcutAdvisor
Springsource で 2 つの同一の問題の説明を見つけました (残念ながら解決されていません)。
http://forum.springsource.org/showthread.php?87428-AspectJPointcutAdvisor-not-Serializable http://forum.springsource.org/archive/index.php/t-57602.html
もちろん、Aspect Orientation を使用することはできませんが、他のサードパーティのライブラリ パーティでも同じ問題が発生する可能性があります。
私がしたことは、ビジネス サービスを保持するインスタンス変数を一時的としてマークすることでした。
public class ManagedBean implements Serializable {
@Inject
private transient ServiceBeanA serviceBeanA;
public void someMethod() {
serviceBean.doSomeBusinessLogic();
}
これは、セッションが復元 (デシリアライズ) されるまで正常に機能します。もちろん、逆シリアル化後、変数 (serviceBeanA) は null です。セッションをシリアル化しないように Web コンテナー (Tomcat など) を構成することもできますが、このアプリケーションはクラウドで実行されるため、サーバーの構成は担当しません。
私が持っていた唯一のアイデアは、提供することによって基本的なJavaシリアライゼーション機能を使用することでした
private synchronized void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
と
private synchronized void writeObject(ObjectOutputStream s) throws IOException
マネージド Bean のメソッド。
private synchronized void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
s.defaultReadObject();
ApplicationContext context = new ClassPathXmlApplicationContext("services.spring-config.xml", "database.spring-config.xml");
this.ServiceBeanA = (ServiceBeanA) context.getBean("serviceBeanA");
}
private synchronized void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
}
このソリューションは機能しますが、非常に不器用で洗練されていないソリューションのようです。サービス Bean を使用するすべてのマネージド Bean で、ほぼ同じコードを繰り返さなければなりません。さらに、管理対象 Bean は、Springs アプリケーション コンテキストをインポートしてサービス変数を復元するため、このように Spring に緊密に結合されます。
誰かがより良いアーキテクチャのアプローチを考えられますか? 前もって感謝します!