注入瞬态@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