如何在反序列化时重新注入瞬态@ManagedProperty? [英] How to re-inject a transient @ManagedProperty at deserializing?

查看:132
本文介绍了如何在反序列化时重新注入瞬态@ManagedProperty?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring和JSF 2创建一个Web应用程序. 业务对象保存在Spring容器中,我使用@ManagedProperty将它们注入到Managed Bean中,如下所示:

I'm using Spring and JSF 2 to create a web application. The business objects are kept in the Spring container, and I inject them in the Managed Beans using the @ManagedProperty, like this:

@ManagedBean
@ViewScoped
public class SomeMB implements Serializable {
    private static final long serialVersionUID = 1L;

    @Getter @Setter
    @ManagedProperty("#{someService}")
    private SomeService someService;
    // ...

问题是,我从 SomeService bean正在使用的Spring( ServiceLocatorFactoryBean )的类不断获取NotSerializableException.

The problem is, I keep getting a NotSerializableException for a class from Spring (ServiceLocatorFactoryBean) that it's being used by the SomeService bean.

如果将其制成transient,反序列化后如何重新注入?

If I make it transient, how could I do the re-injection of it after deserializing?

或者,解决这个问题的其他方法是什么?

Or, what would be other ways to solve this problem?

我已经在这里阅读了其他几个类似的问题,但是找不到与该问题完全相关的任何问题.

I've been reading several other questions similar here, but couldn't find any that dealt exactly with this problem.

推荐答案

而不是通过EL在@ManagedProperty注释中注入Spring bean(在ManagedBean初始化上执行),而是在运行时获取评估EL的bean.

Instead of injecting the Spring beans via EL in a @ManagedProperty annotation (executed on the ManagedBean initialization), obtain the beans evaluating the EL at runtime.

使用这种方法,JSF bean应该是这样的:

With this approach, this is what the JSF beans should look like:

@ManagedBean
@ViewScoped
public class SomeMB implements Serializable {
    private static final long serialVersionUID = 1L;

    private static SomeService someService() {
        return SpringJSFUtil.getBean("someService");
    }
    // ...

以及通过EL获取bean的实用程序类 SpringJSFUtil.java :

And the utility class SpringJSFUtil.java that gets the bean via EL:

import javax.faces.context.FacesContext;

public class SpringJSFUtil {

    public static <T> T getBean(String beanName) {
        if (beanName == null) {
            return null;
        }
        return getValue("#{" + beanName + "}");
    }

    @SuppressWarnings("unchecked")
    private static <T> T getValue(String expression) {
        FacesContext context = FacesContext.getCurrentInstance();
        return (T) context.getApplication().evaluateExpressionGet(context,
                expression, Object.class);
    }
}

这消除了Spring bean属性(以做更多的EL评估为代价),从而避免了将属性放在首位的所有序列化问题.

This eliminates the Spring bean property (at the cost of doing a few more EL evaluations), thus avoiding all the serialization issues of having the property in first place.

使用 OmniFaces 的相同方法:

The same approach, using OmniFaces:

在我的实际代码中,我使用了实用程序类evaluateExpressionGet(String expression)方法. OmniFaces .因此,对于那些也使用它的人,这就是我的代码真正的样子:

In my actual code, I use the evaluateExpressionGet(String expression) method of an utility class available from OmniFaces. So, for those of you who use it too, this is what my code really look like:

import static org.omnifaces.util.Faces.evaluateExpressionGet;

@ManagedBean
@ViewScoped
public class SomeMB implements Serializable {
    private static final long serialVersionUID = 1L;

    private static SomeService someService() {
        return evaluateExpressionGet("#{someService}");
    }
    // ...

请注意,这里的方法获取完整的EL(#{expression}"),而不仅仅是Spring bean的名称(否则您将获得ClassCastException).

这篇关于如何在反序列化时重新注入瞬态@ManagedProperty?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆