java - 错误的 ApplicationContext 中 session 范围的 bean 泄漏

标签 java spring applicationcontext session-scope

我有一个应用程序,它有 2 个 ApplicationContext AB ,其中AB 的父上下文。 B覆盖 A 中的一些 beans ,但也使用了它的一些 bean 。对于前端,我使用 Wicket,并且有两个 Wicket 应用程序 AppAAppB使用各自的 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/

相关文章:

java - VSCode无法导入外部库

java - HQL 中的 Left Join - Hibernate 查询

java - 使用 spring 数据从 mongodb 中选择随机条目

java - 为什么 java.util.Scanner next().charAt(0) 返回 "{",而我的 nextCharIs(scanner ,"{") 方法返回 false?

java - 当我将 django API 连接到 android studio 中的应用程序时,它显示错误

java - 为什么java不支持重启线程

java - Mapstruct 未在生成的源文件中更新其 getter 和 setter

java - 加载 applicationContext 时出现 FileNotFound 异常

java - 多次导入相同的 spring 应用程序上下文文件

java - AbstractApplicationContext(Spring)下的refresh()方法有什么用?为什么使用refresh()后bean单例作用域会丢失?