我目前正面临使用JSF 2和Spring 3 AOP组合的问题。
应用程序被设计为经典的三层结构(Web,服务,数据库)。所以Spring管理的JSF-Beans称Service Beans代表业务逻辑。
Managed Beans看起来像这样:
@Named("startPage")
@Scope("view")
public class ManagedBean implements Serializable {
@Inject
private ServiceBeanA serviceBeanA;
public void someMethod() {
serviceBean.doSomeBusinessLogic();
}
由于这个Bean是视图作用域,它实现了Serializeable,实现变量(在本例中为ServiceBeanA)也是如此,如下所述: JSF backing bean should be serializable?
到目前为止,一切都按预期进行。
现在我想拦截业务服务中声明的业务方法的调用。所以 我创建了一个Aspect,它执行一些基本的日志记录并在spring config中删除它:
<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找到了两个相同的问题描述(遗憾的是没有解决)
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();
}
这个解决方案有效,但它似乎是一个非常笨拙的解决方案。我必须在使用Service Beans的每个Managed Bean中重复几乎相同的代码。此外,Managed bean以这种方式紧密耦合到Spring,因为它们导入Springs Application Context来恢复服务变量。
有人会想到更好的架构方法吗?提前谢谢!