问题
Problem: This injected dependency will always return 0 from SimpleController
- Why does the context get lost for this bean when trying to do dependency injection into an HttpSessionListener implementation?
- What is principles behind this am I missing/confusing for this not to be working?
- 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