gpt4 book ai didi

java - 如何序列化注入(inject)的bean?

转载 作者:行者123 更新时间:2023-12-01 20:15:53 24 4
gpt4 key购买 nike

我想以不同的时间间隔保存注入(inject)的有状态 bean 的数据:更改 - 保存 - 更改 - 保存...我正在使用核心序列化,问题是所有字节数组都是相同的。我相信代理是序列化的,因为如果我稍后反序列化其中一个数组,我就会得到 bean 的当前状态。

序列化未捕获 bean 中的更改的示例:

@Stateful
@RequestScoped
public class State implements Serializable {

private static final long serialVersionUID = 1L;

@Inject
StatelessBean bean; // assume it's needed

private List<String> list = new ArrayList<>();

public void add() {
list.add("S");
}
}

这是一个 JAX-RS 类:

@Stateless
@Path("t1")
public class ChickensResource {

@Inject
State state;

@GET
@Path("/test")
public String test() {
state.add();
byte[] b0 = serialize(state);
System.out.println(b0.length + " " + Arrays.toString(b0));
state.add();
byte[] b1 = serialize(state);
System.out.println(b1.length + " " + Arrays.toString(b1)); // prints same as b0
System.out.println(b0.length + " " + Arrays.toString(b0)); // prints same thing
}

public static <T extends Serializable> byte[] serialize(T s) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos))
{
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

我想做的只是将列表保存在 State 中,因为这是相关数据。我还尝试了 JSON 序列化,它给出了 IOException,但我正在尝试核心序列化。

使用 JavaEE7 和 Wildfly 10.1。

最佳答案

出于各种原因,直接序列化 CDI bean 是危险的:

  • 您可能有一个代理,而不是实际的对象;该对象的依赖关系也是如此
  • 序列化意味着数据将被一次反序列化。但是 CDI bean 由 CDI 管理,并且 CDI 无法将反序列化对象“附加”到其托管对象集中。

但是这个问题的目的是以某种方式保存 CDI bean 的状态,以便以后可以恢复。这可以通过使用另一个保存 CDI bean 状态的对象来完成。这个其他对象不由 CDI 管理,即使用 new 创建,并且是可序列化的。每个需要保留其状态的 CDI bean 都有一对 setState(state)/getState() 方法 - 它们甚至可以是接口(interface)的一部分。您可能希望每个对象也将 setState(state)/getState() 传播给其协作者。

请参阅Memento设计模式。如果您熟悉的话,这也在 JSF 状态保存/恢复机制中实现。

<小时/>

一些示例代码(还有其他有效的方法来做到这一点),从状态接口(interface)开始:

interface HasState<S extends Serializable> {
S getState();
void setState(S state);
}

然后是具有协作者的服务本​​身以及相关的状态对象:

class SomeServiceState implements Serializable {
private String someData;
private Long someId;
private List<String> list;
private CollaboratorState collaboratorState;
// accessors
}

@RequestScoped
public class SomeService implements HasState<SomeServiceState> {

// COLLABORATORS
@Inject
Collaborator collaborator; // assume it's needed

// INTERNAL STATE
private String someData;
private Long someId;
private List<String> list = new ArrayList<>();

public void add() {
list.add("S");
}

// ...

public SomeServiceState getState() {
SomeServiceState state = new SomeServiceState();
state.setSomeData(someData);
state.setSomeId(someId);
state.setList(new ArrayList<>(list)); // IT IS PROBABLY SAFER TO COPY STATE!
// SEE HOW STATE GETS EXTRACTED RECURSIVELY:
state.setCollaboratorState(collaborator.getState());
return state;
}

public void setState(SomeServiceState state) {
someData = state.getSomeData();
someId = state.getSomeId();
list = new ArrayList<>(state.getList());
// SEE HOW STATE GETS APPLIED RECURSIVELY:
collaborator.setState(state.getCollaboratorState());
}
}

协作者及其状态遵循相同的模式:

class CollaboratorState implements Serializable {
private String anyName;
// accessors
}

@RequestScoped
class Collaborator implements HasState<CollaboratorState> {
// you get the point...
}

以及一个示例用法,遵循问题中的代码:

@Stateless
@Path("t1")
public class ChickensResource {

@Inject
SomeService someService;

@GET
@Path("/test")
public String test() {
someService.add();
byte[] b0 = serialize(someService.getState());
// ...
}

public static <T extends Serializable> byte[] serialize(T s) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos))
{
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
<小时/>

编辑:如果服务的客户端需要知道服务具有状态,那么客户端和服务的耦合程度可能会超出预期。一种解决方法是修改 HasState 以处理不透明对象:

interface HasState {
Object getState();
void setState(Object state);
}

客户端的状态包含每个协作者的状态列表:

class SomeServiceState implements Serializable {
private String someData;
private Long someId;
private List<String> list;
private List<Object> collaboratorsState;
// accessors
}

客户端仅在扩展 HasState 时才将协作者添加到状态:

    public Object getState() {
SomeServiceState state = new SomeServiceState();
state.setSomeData(someData);
state.setSomeId(someId);
state.setList(new ArrayList<>(list));
if( collaborator instanceof HasState ) {
state.getCollaboratorsState().add(collaborator.getState());
}
return state;
}

关于java - 如何序列化注入(inject)的bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45828159/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com