我有一个不可序列化的服务类和一个必须可序列化但必须能够访问该服务类的 bean:
class SomeBean implements Serializable
{
private StuffFactory factory;
@Autowired
public SomeBean(StuffFactory factory)
{
this.factory = factory;
}
public getOther()
{
return this.factory.getSomeOtherStuff();
}
}
这显然行不通,因为现在 SomeBean
类不再是可序列化的。在 Spring 中解决这个问题的正确方法是什么?当我使 factory
字段成为 transient 时,我是否在反序列化时松开了注入(inject)的工厂实例?当我使 StuffFactory
也可序列化时,此类将不再是单例,因为每个 SomeBean
实例在反序列化后都会有自己的工厂。
最佳答案
要使这个魔法发挥作用,您需要某种背景。
我能想到的一个丑陋的方法是静态 ThreadLocal
持有 ApplicationContext
- 这就是 spring-security 使用 SecurityContextHolder
的工作方式。
但如果您能够将需要 StuffFactory
的逻辑外部化为某种单例 SomeBeanService
,那就最好了,即:
public class SomeBeanService {
@Autowired
private StuffFactory stuffFactory;
public void doWithSomeBean(SomeBean bean) {
// do the stuff using stuffFactory here
}
}
更新:
上述 ThreadLocal
替代方案的重点是完全摆脱 SomeBean
对 StuffFactory
的依赖。这应该是可能的,但需要更改架构。 关注点分离(不仅是 Spring 的基本规则之一)意味着让 SomeBean
成为一个简单的数据传输对象<可能是个好主意/em> 以及要移动到服务层的业务逻辑。
如果您无法实现这一点,那么唯一的方法就是使用某种static
上下文(正如 Ralph 所说)。此类上下文的实现可能涉及使用 ThreadLocal
。这将允许访问 ApplicationContext
以获取 StuffFactory
,但它几乎与全局变量一样丑陋,因此请尽可能避免使用它。
更新2:
我刚刚看到您的评论,SomeBean
存储在 HTTP session 中,因此存在序列化/反序列化问题。现在我更建议更改您的设计并删除依赖项。使 SomeBean
成为一个简单的 DTO,尽可能小以避免 session 过载。在 SomeBean
中不应该有需要访问单例 Spring bean 的逻辑。这样的逻辑应该放在controller或者service层。
关于java - 将 Spring 依赖注入(inject)到可序列化的 bean 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7763627/