会话范围的bean在错误的ApplicationContext中泄漏

时间:2018-02-22 08:14:07

标签: java spring applicationcontext session-scope

我有一个应用程序,它有2个ApplicationContexts AB,其中AB的父上下文。 B覆盖了A中的一些bean,但也使用了一些bean。对于前端,我使用Wicket,我有两个Wicket应用程序AppAAppB使用相应的Spring ApplicationContext。

问题现在出现在会话范围的bean sessionBean上,我有两个不同的实现:A定义一个返回sessionBeanA实例的工厂方法,{{1}有一个具有相同签名的工厂方法返回B的实例。 用户现在打开sessionBeanB,在后端,我们得到AppB的实例,只要我们注入sessionBeanB,就像我们预期的那样。 但是,如果用户现在离开sessionBean并打开AppB(仍然使用相同的基础会话),我们会在AppA中注入sessionBeanB的实例,因为{{ 1}}对象仍然保存先前创建的bean对象。

如何防止会话范围的bean在另一个ApplicationContext中泄漏? ApplicationContext A不应该打扰来自SessionScope ...

的bean

非常感谢任何帮助。

2 个答案:

答案 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