在序列化方面,Spring会话范围的bean(控制器)和对服务的引用

Boz*_*zho 43 java jsf serialization spring servlets

  • 标准案例 - 你有一个控制器(@Controller)@Scope("session").
  • 例如,通常期望放入会话中的类实现,Serializable以便在服务器重新启动时可以物理存储它们
  • 如果控制器实现Serializable,这意味着它所引用的所有服务(其他spring bean)也将被序列化.它们通常是代理,引用了交易管理器,实体管理器工厂等.
  • 某些服务甚至控制器ApplicationContext通过实现来保持对引用的引用并不是不太可能ApplicationContextAware,因此这可以有效地意味着整个上下文被序列化.并且鉴于它拥有许多连接 - 即不能通过思想序列化的东西,它将在腐败状态下恢复.

到目前为止,我大多忽略了这些问题.最近我想到声明我所有的spring依赖项transientreadResolve()通过静态实用程序类将它们重新WebApplicationContextUtils导入,并将请求/ ServletContext保存在ThreadLocal.这很乏味,但它保证了,当反序列化对象时,它的依赖关系将与当前应用程序上下文"保持同步" .

是否有任何公认的做法,或任何序列化春季背景部分的指南.

请注意,在JSF中,托管bean(~controller)是有状态的(与基于动作的Web框架不同).所以也许我的问题更多的是JSF,而不是spring-mvc.

Han*_*eek 19

此演示文稿(约1:14)扬声器说,这个问题是在春季3.0解决提供不可序列豆的代理,从获取实例当前应用程序上下文(上反序列化)


lah*_*her 7

I would expect to scope controllers as 'singleton', i.e. once per application, rather than in the session.

Session-scoping is typically used more for storing per-user information or per-user features.

Normally I just store the 'user' object in the session, and maybe some beans used for authentication or such. That's it.

Take a look at the spring docs for configuring some user data in session scope, using an aop proxy:

http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes-other-injection

希望有所帮助


mer*_*ike 7

似乎赏金没有吸引一个答案,所以我将记录我有限的理解:

@Configuration
public class SpringConfig {

    @Bean 
    @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 
    MyService myService() {
        return new MyService();
    }

    @Bean
    @Scope("request")
    public IndexBean indexBean() {
        return new IndexBean();
    }

    @Bean
    @Scope("request")
    public DetailBean detailBean() {
        return new DetailBean();
    }
}

public class IndexBean implements Serializable {

    @Inject MyService myService;

    public void doSomething() {
        myService.sayHello();
    }
}

public class MyService {
    public void sayHello() {
        System.out.println("Hello World!");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,Spring不会将裸MyService注入到IndexBean中,而是将序列化代理注入其中.(我测试了它,并且它有效).

但是,spring文档写道:

不是需要使用<aop:scoped-proxy/>与和作用域为豆类结合singletonsprototypes.如果您尝试为单例bean创建范围代理,BeanCreationException则会引发该代理.

至少在使用基于java的配置时,可以很好地实例化bean及其代理,即不抛出异常.但是,看起来使用范围代理来实现可串行化并不是这种代理的预期用途.因此我担心Spring可能会修复"bug"并阻止通过基于Java的配置创建范围代理.

此外,还有一个限制:重新启动Web应用程序后,代理的类名称会有所不同(因为代理的类名基于用于构造它的建议的哈希码,而这又取决于hashCode的一个拦截器的类对象.Class.hashCode不会覆盖Object.hashCode,它在重启时不稳定).因此,其他VM或重新启动时不能使用序列化会话.