会话范围的bean未实例化

时间:2013-12-12 12:50:41

标签: java spring session servlets

我想创建一个会话范围的bean来监视HTTP会话的激活和钝化。豆非常简单:

package my.log;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;

import org.apache.log4j.Logger;

public class SessionLoggingListenerBean implements HttpSessionActivationListener {
    private final Logger LOG = Logger.getLogger(this.getClass());

    public SessionLoggingListenerBean() {
        LOG.info("SessionLoggingListenerBean starting");
    }

    public void init() {
        LOG.info("SessionLoggingListenerBean init");
    }

    public void sessionDidActivate(HttpSessionEvent event) {
        LOG.info("Session " + event.getSession().getId() + " activated");
    }

    public void sessionWillPassivate(HttpSessionEvent event) {
        LOG.info("Session " + event.getSession().getId() + " will passivate");
    }
}

应用程序上下文中的Bean定义:

 <bean id="sessionLoggingListenerBean" class="my.log.SessionLoggingListenerBean" scope="session" init-method="init" lazy-init="false"/>

使用此配置,即使是构造函数或init()方法,也没有来自此类的日志。显然,Spring不会创建这个bean 通过反复试验,我检查了Spring在另一个bean需要时实例化这样一个bean,例如:用于UI。还有其他(更好)的方式吗?这是春天的错误吗? 使用的Spring版本:2.0.8。

2 个答案:

答案 0 :(得分:2)

HttpSessionActivationListenerjavax.servlet.http包的一部分。这应该给你一个提示,它应该由Servlet容器管理。在您的情况下,您没有通过ListenerServletContextweb.xml注册SerlvetContainerInitializer

通过web.xml,您将无法将其作为Spring和Servlet容器托管对象,因此存在这些变通方法,firstsecond

如果您使用的是WebApplicationInitializer,则可以实例化AnnotationConfigWebApplicationContext,创建SessionLoggingListenerBean bean,检索它并将其与

一起使用
SessionLoggingListenerBean yourBean = context.getBean(SessionLoggingListenerBean.class);
servletContext.addListener(yourBean);

答案 1 :(得分:0)

经过一些实验后,我认为最好不要将Spring用于此目的。我已经修改了类来实现HttpSessionListener和Serializable:

public class SessionLoggingListener implements HttpSessionListener,
    HttpSessionActivationListener, Serializable {
private static final long serialVersionUID = -763785365219658010L;
private static final Logger LOG = Logger.getLogger(SessionLoggingListener.class);

public SessionLoggingListener() {
    LOG.info("SessionLoggingListener created");
}

public void sessionDidActivate(HttpSessionEvent event) {
    LOG.info("Session " + event.getSession().getId() + " activated");
}

public void sessionWillPassivate(HttpSessionEvent event) {
    LOG.info("Session " + event.getSession().getId() + " will passivate");
}

public void sessionCreated(HttpSessionEvent event) {
    final HttpSession session = event.getSession();
    LOG.info("Session " + session.getId() + " created. MaxInactiveInterval: " + session.getMaxInactiveInterval() + " s");
    session.setAttribute(this.getClass().getName(), this);
}

public void sessionDestroyed(HttpSessionEvent event) {
    LOG.info("Session " + event.getSession().getId() + " destroyed");
    event.getSession().removeAttribute(this.getClass().getName());
}

}

并将其添加到web.xml:

<listener>
    <listener-class>
        evo.log.SessionLoggingListener
    </listener-class>
</listener>

从现在开始,无论何时创建新会话,侦听器都会绑定它(session.setAttribute(...))。这是使容器注意到关于会话激活或钝化的监听器所必需的。


对于Spring和会话 - 根据此forum thread Spring在请求会话bean之前不加载会话bean:

  

会话bean被视为“原型”的特殊形式。这意味着它将在创建实例时遵循原型语义。

对我而言,这是一种不直观且没有很好记录的行为。