我有一个应用程序,它有 2 个 ApplicationContext A
和B
,其中A
是 B
的父上下文。 B
覆盖 A
中的一些 beans ,但也使用了它的一些 bean 。对于前端,我使用 Wicket,并且有两个 Wicket 应用程序 AppA
和AppB
使用各自的 Spring ApplicationContext。
现在问题出现在 session 范围的 bean sessionBean
上。 ,我有两种不同的实现: A
定义一个返回 sessionBeanA
实例的工厂方法, B
有一个具有相同签名的工厂方法,返回 sessionBeanB
的实例。
用户现在打开AppB
在后端,我们得到一个 sessionBeanB
的实例,无论我们在哪里注入(inject) sessionBean
,正如我们所期望的那样。
但是,如果用户现在离开 AppB
并打开 AppA
(仍然使用相同的底层 session ),我们得到一个 sessionBeanB
的实例注入(inject)A
,因为SessionScope
object 仍然保存先前创建的 bean 对象。
如何防止 session 范围的 bean 在不同的 ApplicationContext 中泄漏?应用程序上下文A
不必为 B
中的 bean 烦恼...
非常感谢任何帮助。
最佳答案
可以通过使用 CustomScopeConfigurer
从 Spring 扩展 SessionScope
来考虑 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();
}
关于java - 错误的 ApplicationContext 中 session 范围的 bean 泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48922480/