1、在java web项目中我们通常会有这样的需求:
当项目启动时执行一些初始化操作,例如从数据库加载全局配置文件等,通常情况下我们会用JavaEE规范中的Listener去实现
public class ConfigListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//执行初始化操作
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
2、这样当servlet容器初始化完成后便会调用contextInitialized方法。但是通常我们在执行初始化的过程中会调用service和dao层提供的方法,而现在web项目通常会采用spring框架来管理和装配bean,我们想当然会像下面这么写,假设执行初始化的过程中需要调用ConfigService的initConfig方法,而ConfigService由spring容器管理(标有@Service注解)
public class ProductListener implements ServletContextListener {
@Autowired
private ProductService productService;
@Override
public void contextInitialized(ServletContextEvent sce) {
productService.queryAll();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
(1)Listener的生命周期是由servlet容器(例如tomcat)管理的,项目启动时上例中的ConfigListener是由servlet容器实例化并调用其contextInitialized方法,而servlet容器并不认得@Autowired注解,因此导致ConfigService实例注入失败。
(2)而spring容器中的bean的生命周期是由spring容器管理的。
4.那么该如何在spring容器外面获取到spring容器bean实例的引用呢?这就需要用到spring为我们提供的WebApplicationContextUtils工具类,该工具类的作用是获取到spring容器的引用,进而获取到我们需要的bean实例。代码如下
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.Test.entity.Product;
import com.Test.service.productService;
/**
* 监听器实现定时任务
* @author hph
*
*/
public class OrderTimerRunnable implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
@Override
public void contextInitialized(final ServletContextEvent sce) {
TimerTask task=new TimerTask(){
@Override
public void run() {
System.out.println("监听器获得spring容器的数据");
ProductService productService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(ProductService.class);
List<Product> ordersList = productService.queryAll();
System.out.println("数据打印--------------------------"+ordersList);
}
};
Timer timer=new Timer();
timer.scheduleAtFixedRate(task, 0, 5000);
}
}
注意:以上代码有一个前提,那就是servlet容器在实例化ConfigListener并调用其方法之前,要确保spring容器已经初始化完毕!而spring容器的初始化也是由Listener(ContextLoaderListener)完成,因此只需在web.xml中先配置初始化spring容器的Listener,然后在配置自己的Listener,配置如下
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.test.OrderTimerRunnable</listener-class>
</listener>