3

我目前在使用 JSF 2 和 Spring 3 AOP 的组合时遇到问题。

应用程序设计为经典的三层架构(Web、服务、数据库)。所以 Spring 管理的 JSF-Beans 调用代表业务逻辑的 Service Beans。

托管 Bean 如下所示:

@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 配置中将其删除:

<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)为空。我可以将 Web 容器(例如 Tomcat)配置为不序列化会话,但该应用程序在云中运行,因此我不负责配置服务器。

我唯一的想法是通过提供

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 以这种方式与 Spring 紧密耦合,因为它们导入 Springs 应用程序上下文以恢复服务变量。

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

4

0 回答 0