使用Spring AOP时,JSF中的NotSerializableException

时间:2013-01-23 19:32:35

标签: java serialization jsf-2 deserialization spring-aop

我目前正面临使用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来恢复服务变量。

有人会想到更好的架构方法吗?提前谢谢!

0 个答案:

没有答案