我有一个应用程序,它有2个ApplicationContexts A
和B
,其中A
是B
的父上下文。 B
覆盖了A
中的一些bean,但也使用了一些bean。对于前端,我使用Wicket,我有两个Wicket应用程序AppA
和AppB
使用相应的Spring ApplicationContext。
问题现在出现在会话范围的bean sessionBean
上,我有两个不同的实现:A
定义一个返回sessionBeanA
实例的工厂方法,{{1}有一个具有相同签名的工厂方法返回B
的实例。
用户现在打开sessionBeanB
,在后端,我们得到AppB
的实例,只要我们注入sessionBeanB
,就像我们预期的那样。
但是,如果用户现在离开sessionBean
并打开AppB
(仍然使用相同的基础会话),我们会在AppA
中注入sessionBeanB
的实例,因为{{ 1}}对象仍然保存先前创建的bean对象。
如何防止会话范围的bean在另一个ApplicationContext中泄漏? ApplicationContext A
不应该打扰来自SessionScope
...
非常感谢任何帮助。
答案 0 :(得分:1)
可以从Spring扩展SessionScope
,也可以使用CustomScopeConfigurer
来考虑ApplicationContext,如下所示:
import org.springframework.beans.factory.config.CustomScopeConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public final class SessionScopeConfigurer extends CustomScopeConfigurer implements ApplicationContextAware {
private final CustomSessionScope scope;
public SessionScopeConfigurer() {
scope = new CustomSessionScope();
// Overwrite the session scope added by Spring
addScope("session", scope);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
scope.setApplicationContextId(applicationContext.getId());
}
}
其中CustomSessionScope
是:
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.web.context.request.SessionScope;
/**
* Extends {@link SessionScope} by modifying all bean names, so that they are specific to their ApplicationContext.
* This avoids session-scoped beans from context a leaking through context b.
*/
public class CustomSessionScope extends SessionScope {
private String applicationContextId;
public void setApplicationContextId(String applicationContextId) {
this.applicationContextId = applicationContextId;
}
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
return super.get(modify(name), objectFactory);
}
@Override
public Object remove(String name) {
return super.remove(modify(name));
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
super.registerDestructionCallback(modify(name), callback);
}
private String modify(String name) {
// Attach ApplicationContextId to the bean name
return name + applicationContextId;
}
}
您可以在Java Spring配置类中使用它:
@Bean
public static CustomScopeConfigurer configureSessionScope() {
return new SessionScopeConfigurer();
}
答案 1 :(得分:0)
改变豆类的范围可能会有所帮助。将范围缩小到@conversation。
在这里,您将找到有关上下文范围的更多信息:
https://docs.jboss.org/weld/reference/2.4.0.CR1/en-US/html/scopescontexts.html