Dependency Injection inside of HttpSessionListener implementation

两盒软妹~` 提交于 2019-12-19 04:15:25

问题


Problem: This injected dependency will always return 0 from SimpleController

  1. Why does the context get lost for this bean when trying to do dependency injection into an HttpSessionListener implementation?
  2. What is principles behind this am I missing/confusing for this not to be working?
  3. How do I fix this?

Project on Github webApp project Source

Consider the following:

SessionCounterListener

public class SessionCounterListener implements HttpSessionListener {

  @Autowired
  private SessionService sessionService;

  @Override
  public void sessionCreated(HttpSessionEvent arg0) {
    sessionService.addOne();
  }

  @Override
  public void sessionDestroyed(HttpSessionEvent arg0) {
    sessionService.removeOne();
  } 
}

web.xml

<web-app ...>
    <listener>
        <listener-class>com.stuff.morestuff.SessionCounterListener</listener-class>
    </listener>

</web-app>

applicationContext.xml

<xml ...>

   <!-- Scan for my SessionService & assume it has been setup correctly by spring-->
   <context:component-scan base-package="com.stuff"/>

</beans>

Service: SessionService

@Service
public class SessionService{

  private int counter = 0;

  public SessionService(){}

  public void addOne(){
    coutner++;
  }

  public void removeOne(){
    counter--;
  }

  public int getTotalSessions(){
     return counter;
  }

}

Controller: SimpleController

@Component
public SimpleController
{
  @Autowired
  private SessionService sessionService;

  @RequestMapping(value="/webAppStatus")
  @ResponseBody
  public String getWebAppStatus()
  {
     return "Number of sessions: "+sessionService.getTotalSessions();
  }

}

回答1:


When you declare a <listener> in web.xml like so

<listener>
    <listener-class>com.stuff.morestuff.SessionCounterListener</listener-class>
</listener>

you are telling your Servlet container to instantiate the class specified in the listener-class element. In other words, this instance will not be managed by Spring and it will therefore not be able to inject anything and the field will remain null.

There are workarounds to this. And some more.

Note that this

<!-- Scan for my SessionService & assume it has been setup correctly by spring-->
<context:component-scan base-package="com.stuff"/>

is not a valid entry in web.xml. I don't know if that was a copy mistake on your part.




回答2:


This is an answer here that shows the actual solution.

You should modify SessionCountListener like this, and the above example will work:

public class SessionCounterListener implements HttpSessionListener {

  @Autowired
  private SessionService sessionService;

  @Override
  public void sessionCreated(HttpSessionEvent arg0) {
    getSessionService(se).addOne();
  }

  @Override
  public void sessionDestroyed(HttpSessionEvent arg0) {
    getSessionService(se).removeOne();
  }

  private SessionService getSessionService(HttpSessionEvent se) {
    WebApplicationContext context = 
      WebApplicationContextUtils.getWebApplicationContext(
        se.getSession().getServletContext());
    return (SessionService) context.getBean("sessionService");
  } 
}


来源:https://stackoverflow.com/questions/20476760/dependency-injection-inside-of-httpsessionlistener-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!