CDI会话作用域Bean的非懒加载实例化

3
CDI新手问题。简单的测试场景:JSF + CDI SessionScoped beans。
我需要一种优雅的方法来实例化一组已知的会话作用域CDI bean,而不需要在JSF页面上提及它们或从其他bean中调用它们的方法。作为测试案例 - 一个简单的日志记录bean,它只是记录http会话的开始和结束时间。
当然,我可以创建一个空的JSF组件,将其放置在全站模板内,并使其触发所需会话bean的虚拟方法,但我认为这样有点丑陋。
我看到的另一个选择是选择一个单独的会话bean(它要么通过JSF中的EL完全初始化,要么通过其他bean的引用),并使用其@PostConstruct方法来触发其他会话bean - 这个解决方案比前一个要稍微好一些。
看起来我错过了什么,我会感激任何其他想法。

对于您的测试用例,我建议使用HttpSessionListener。您能提供一个真实的用例来说明您需要这样做吗? - Luiggi Mendoza
@LuiggiMendoza,谢谢,我忘记了会话监听器,尽管我曾经在JSF bean中使用SessionBindingListener。至于实际情况,我说这是一个新手问题,我试图解耦许多会话类与交叉引用,并发现其中一些需要在会话启动和销毁时执行某些活动 - 主要是日志记录和安全性方面的事情。 - andbi
2个回答

3

在接受Karl的答案并感谢Luiggi的提示的同时,我也发布了我的解决方案,它基于HttpSessionListener,但不需要与BeanProviderBeanManager打交道。

@WebListener
public class SessionListener implements HttpSessionListener {

  @Inject
  Event<SessionStartEvent> startEvent;
  @Inject
  Event<SessionEndEvent> endEvent;

  @Override
  public void sessionCreated(HttpSessionEvent se) {
    SessionStartEvent e = new SessionStartEvent();
    startEvent.fire(e);
  }

  @Override
  public void sessionDestroyed(HttpSessionEvent se) {
    SessionEndEvent e = new SessionEndEvent();
    endEvent.fire(e);
  }
}

令我惊讶的是,上述代码实例化了所有观察这些事件的bean:
@Named
@SessionScoped
public class SessionLogger implements Serializable {

  @PostConstruct
  public void init() {
    // is called first
  }

  public void start(@Observes SessionStartEvent event) {
    // is called second
  }
}

确实是最佳解决方案,您应该将其标记为正确答案。 - Karl Kildén

1

是的,HttpSessionListener 可以实现这个功能。只需注入 bean 并调用它们即可。

如果您的容器不支持在 HttpSessionListener 中进行注入,您可以查看 deltaspike 核心和 BeanProvider

http://deltaspike.apache.org/core.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接