注入瞬态@ManagedProperty反序列化?

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

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

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

问题是,我一直从Spring获得一个NotSerializableException (ServiceLocatorFactoryBean),它被SomeService bean使用。

如果我把它作为transient ,我怎么能在反序列化之后重新注入它呢?

或者,还有其他方法可以解决这个问题吗?

我一直在阅读其他几个类似的问题,但找不到任何与此问题完全相关的问题。


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

通过这种方法,这就是JSF bean的外观:

@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:

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评估为代价),从而避免了将属性放在第一位的所有序列化问题。

使用OmniFaces的相同方法:

在我的实际代码中,我使用OmniFaces中可用的实用类的evaluateExpressionGet(String expression)方法。 所以,对于那些使用它的人来说,这就是我的代码真正的样子:

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)。


在您的Spring @Service上尝试@Scope(value = BeanDefinition.SCOPE_SINGLETON,proxyMode = ScopedProxyMode.INTERFACES)。 这应该将一个可序列化的代理对象注入到您的托管bean中,这将在反序列化后访问服务时重新定位服务。


对于那些遵循 - 我有一个类似的问题与注入ResourceBundle。 使用BalusC的答案的一部分,我做了以下几点:

@ManagedProperty(value="#{myBundle}")
private transient ResourceBundle myBundle;

private Object readResolve() {
    myBundle = FacesContext.getCurrentInstance().getApplication()
        .evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{myBundle}",
        ResourceBundle.class);
    return this;
}

这样,只有在托管bean被反序列化时才评估EL。

链接地址: http://www.djcxy.com/p/59469.html

上一篇: inject a transient @ManagedProperty at deserializing?

下一篇: Custom ResourceProviderFactory Dependency Injection