在Listener(监听器)定时启动的TimerTask(定时任务)中使用Spring@Service注解的bean
1.有时候在项目中需要定时启动某个任务,对于这个需求,基于JavaEE规范,我们可以使用Listener与TimerTask来实现,代码如下:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
2.contextInitialized方法中新建了一个定时管理器,代码如下:
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager() {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask();
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
3.在定时任务的Constructor中新建了一个定时任务,其代码如下:
@Configuration
public class TestTimerTask extends TimerTask {
//采用Spring框架的依赖注入
@Autowired
private SelectDataService selectDataService; public TestTimerTask() {
super();
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
spring是个性能非常优秀的抽象工厂,可以生产出工程所需要的实例,这里采用Spring容器的自动注入selectDataService实例。上面代码中,selectDataService这个类是采用Spring的@Service注解的,在项目中主要通过Spring容器注入到Controller中,其作用主要用来访问数据库。
运行项目将会发现NullPointerException,也就是说SelectDataService的实例没有被注入到变量selectDataService中。那么,这是什么原因呢?首先来看看配置文件。
下面是web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.test.TestTaskListener</listener-class>
</listener>
在启动web项目时,Servlet容器(比如Tomcat)会读web.xml配置文件中的两个节点和,节点用来加载appliactionContext.xml(即Spring的配置文件),节点用来创建监听器(比如TestTaskListener)实例。Listener的生命周期是由servlet容器管理的,例中的TestTaskListener是由servlet容器实例化并调用其contextInitialized方法的,但是,SelectDataService是通过@Service注解的,也就是说SelectDataService是由Spring容器管理的,在Spring容器外无法直接通过依赖注入得到Spring容器管理的bean实例的引用。为了在Spring容器外得到Spring容器管理的bean,可以使用Spring提供的工具类WebApplicationContextUtils。也就是说,可以在servlet容器管理的Listener中使用该工具类获Spring管理的bean。
看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
那么在Listener中获得的SelectDataService实例如何在TestTimerTask中使用呢?可以通过作为参数传递过去,看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager(selectDataService);
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager(SelectDataService selectDataService) {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask(selectDataService);
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
@Configuration
public class TestTimerTask extends TimerTask {
private SelectDataService selectDataService;
public TestTimerTask(SelectDataService selectDataService) {
super();
this.selectDataService = selectDataService;
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
再回到web.xml
由于Servlet容器在初始化TestTaskListener时,获取了Spring容器,所以必须保证,在此之前,Spring容器已经初始化完成。因为Spring容器的初始化也是由Listener(ContextLoaderListener)完成,该监听器用Spring框架提供,可以在web应用启动时启动Spring容器。所以,在web.xml中,要先配置ContextLoaderListener,再配置TestTaskListener。
1.有时候在项目中需要定时启动某个任务,对于这个需求,基于JavaEE规范,我们可以使用Listener与TimerTask来实现,代码如下:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
2.contextInitialized方法中新建了一个定时管理器,代码如下:
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager() {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask();
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
3.在定时任务的Constructor中新建了一个定时任务,其代码如下:
@Configuration
public class TestTimerTask extends TimerTask {
//采用Spring框架的依赖注入
@Autowired
private SelectDataService selectDataService;
public TestTimerTask() {
super();
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
spring是个性能非常优秀的抽象工厂,可以生产出工程所需要的实例,这里采用Spring容器的自动注入selectDataService实例。上面代码中,selectDataService这个类是采用Spring的@Service注解的,在项目中主要通过Spring容器注入到Controller中,其作用主要用来访问数据库。
运行项目将会发现NullPointerException,也就是说SelectDataService的实例没有被注入到变量selectDataService中。那么,这是什么原因呢?首先来看看配置文件。
下面是web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.test.TestTaskListener</listener-class>
</listener>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在启动web项目时,Servlet容器(比如Tomcat)会读web.xml配置文件中的两个节点和,节点用来加载appliactionContext.xml(即Spring的配置文件),节点用来创建监听器(比如TestTaskListener)实例。Listener的生命周期是由servlet容器管理的,例中的TestTaskListener是由servlet容器实例化并调用其contextInitialized方法的,但是,SelectDataService是通过@Service注解的,也就是说SelectDataService是由Spring容器管理的,在Spring容器外无法直接通过依赖注入得到Spring容器管理的bean实例的引用。为了在Spring容器外得到Spring容器管理的bean,可以使用Spring提供的工具类WebApplicationContextUtils。也就是说,可以在servlet容器管理的Listener中使用该工具类获Spring管理的bean。
看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager();
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
那么在Listener中获得的SelectDataService实例如何在TestTimerTask中使用呢?可以通过作为参数传递过去,看如下代码:
public class TestTaskListener implements ServletContextListener {
//Context()初始化方法
@Override
public void contextInitialized(ServletContextEvent sce) {
//获得Spring容器
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
//从Spring容器中获得SelectDataServlet的实例
SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
//新建一个定时管理器
new TestTimerManager(selectDataService);
}
public TestTaskListener() {
super();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
public class TestTimerManager {
//新建一个定时器
Timer timer = new Timer();
public TestTimerManager(SelectDataService selectDataService) {
super();
//新建一个定时任务
TestTimerTask task = new TestTimerTask(selectDataService);
//设置定时任务
timer.schedule(task, firstTimeToStartTheTask, period);
}
}
@Configuration
public class TestTimerTask extends TimerTask {
private SelectDataService selectDataService;
public TestTimerTask(SelectDataService selectDataService) {
super();
this.selectDataService = selectDataService;
}
@Override
public void run(){
try {
//访问数据库
MyData myData = selectDataService.selectMyDataById(id);
}catch(Exception ex) {
System.out.println("定时任务出错");
ex.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
再回到web.xml
由于Servlet容器在初始化TestTaskListener时,获取了Spring容器,所以必须保证,在此之前,Spring容器已经初始化完成。因为Spring容器的初始化也是由Listener(ContextLoaderListener)完成,该监听器用Spring框架提供,可以在web应用启动时启动Spring容器。所以,在web.xml中,要先配置ContextLoaderListener,再配置TestTaskListener。
在Listener(监听器)定时启动的TimerTask(定时任务)中使用Spring@Service注解的bean的更多相关文章
- atititt.java定时任务框架选型Spring Quartz 注解总结
atititt.java定时任务框架选型Spring Quartz 总结 1. .Spring Quartz (ati recomm) 1 2. Spring Quartz具体配置 2 2.1. 增 ...
- 如何在自定义Listener(监听器)中使用Spring容器管理的bean
正好以前项目中碰到这个问题,现在网上偶然又看到这个问题的博文,那就转一下吧. 原文:http://blog.lifw.org/post/46428852 感谢作者 另外补充下:在web Server容 ...
- quartz 框架定时任务,使用spring @Scheduled注解执行定时任务
配置quartz 在spring中需要三个jar包: quartz-1.6.5.jar.commons-collections-3.2.jar.commons-logging-1.1.jar 首先要配 ...
- 服务器启动完成执行定时任务Timer,TimerTask
由于项目需求:每隔一段时间就要调外部接口去进行某些操作,于是在网上找了一些资料,用了半天时间弄好了,代码: import java.util.TimerTask; public class Accou ...
- Listener监听器和Filter过滤器
Listener监听器 WEB中的监听器 WEB 中的 Listener 和 Filter 是属于 Servlet 规范中的高级的技术.WEB中的监听器共有三类八种(监听三个域对象)* 事件源:Ser ...
- TimerTask定时任务
web.xml <listener> <listener-class>com.sign.listener.NFDFlightDataTaskListener</liste ...
- [Java] JSP笔记 - Listener 监听器
Java Web 开发时,可以使用 Listener 来监听来监听一些事件,从而实现一些功能.实际上这个监听器,原理就是 Delphi 中大家常用的各种事件. 1. 那么,监听器的主要用途用哪些呢: ...
- listener监听器的相关知识
从别人的博客上我学习了listener的相关知识现在分享给大家 1.概念: 监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上 ...
- listener监听器
前言:之前写了一篇关于Filter的文章:http://tianweili.github.io/blog/2015/01/26/java-filter/,现在再来一篇Listener的,Filter和 ...
随机推荐
- REST构架风格介绍之二:CRUD
转载自:Todd Wei http://www.cnblogs.com/weidagang2046/archive/2009/05/09/1453065.html 上一节我们通过两个例子初步体 ...
- RV32A指令集
RV32A指令包括两类:AMO(atomic memory operation)指令,Load-Reserved/Store-Conditional指令 Category Fmt RV32I base ...
- iOS开发-UINavigationBar和Status Bar实用技巧
iOS7之后关于UINavigationBar和Status Bar都发生了一系列的改变,如果不需要兼容iOS7之后的设备,按照网上有些资料去解决问题会踩到一些坑.在iOS 7中,我们可以修改每个V ...
- javascript对象constructor属性
概述 返回一个指向创建了该对象原型的函数引用.需要注意的是,该属性的值是那个函数本身,而不是一个包含函数名称的字符串.对于原始值(如1,true 或 "test"),该属性为只读. ...
- cmd怎么删除Oracle数据库中的用户实例
Oracle数据库使用过程中,针对系统都会建立独立的数据库用户,但有些时候处于测试或别的原因需要删除,原来的DB用户,这时我们可以使用下面的办法. 下属操作的前提是——确保数据库服务及监听均处于启动状 ...
- tf.concat, tf.stack和tf.unstack的用法
tf.concat, tf.stack和tf.unstack的用法 tf.concat相当于numpy中的np.concatenate函数,用于将两个张量在某一个维度(axis)合并起来,例如: a ...
- CHtmlEditCtrl (2): Add a Source Text Editor to Your HTML Editor
In a previous article, I described how to create an HTML editor using the MFC CHtmlEditCtrl class in ...
- Andriod NDK编译的时候无法使用math.h的函数。
编译NDK项目的时候,当用到sinf的时候,编译报错: 选中sinf函数,右键Go to declaration, 发现math.h的文件路径是: c:\ProgramData\Microsoft\A ...
- rabbitMQ在linux上安装
语言环境安装 一.编译安装方式 1.依赖环境的安装-如果需要用编译安装erlang语言环境,需要安装C++编译. yum -y install make gcc gcc-c++ kernel-deve ...
- FIS.js前端开发的使用说明文档
文档结构 什么是FIS 部署FIS FIS基本使用 模块定义 加载方式 调用Tangram 2.0 一.什么是FIS FIS提供了一套贯穿开发流程的开发体系和集成开发环境,为产品线提供前端开发底层架构 ...