如何序列化注入的bean?

如何序列化注入的bean?,第1张

如何序列化注入的bean?

由于各种原因,直接序列化CDI bean很危险:

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

但是,此问题的目的是以某种方式保存CDI bean的状态,以便以后可以将其还原。这可以通过使用另一个保存CDI
bean状态的对象来实现。该其他对象不受CDI管理,即由创建

new
,并且可序列化。每个需要保持其状态的CDI
bean都有一对
setState(state)
/
getState()
方法-
它们甚至可以是接口的一部分。你可能希望每个对象传播
setState(state)
/
getState()
它的合作者了。

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


从状态接口开始的一些示例代码(还有其他有效的方法):

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}@RequestScopedpublic 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}@RequestScopedclass 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;    }


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5507599.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存