在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和 ...
随机推荐
- 第十章 dubbo线程模型
一 netty的线程模型 在netty中存在两种线程:boss线程和worker线程. 1 boss线程 作用: accept客户端的连接: 将接收到的连接注册到一个worker线程上 个数: 通常情 ...
- [leetcode]Unique Binary Search Trees @ Python
原题地址:https://oj.leetcode.com/problems/unique-binary-search-trees/ 题意: Given n, how many structurally ...
- Tensorflow 模型持久化saver及加载图结构
主要内容: 1. 直接保存,加载模型; (可以指定加载,保存的var_list) 2. 加载,保存指定变量的模型 3. slim加载模型使用 4. 加载模型图结构和参数等 tensorflow 恢复部 ...
- 集合 enum 枚举 简介 案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 使用C#开发一个简单的P2P应用
作者: 刘彦青 本篇文章讨论了一种设计P2P网络应用程序的简单方法. 尽管有许多P2P网络不需要索引服务器或中央服务器,各客户机之间可以互相直接通讯,但下面的图1还是显示了P2P网络的基本工作原理,一 ...
- Word Embedding与Word2Vec
http://blog.csdn.net/baimafujinji/article/details/77836142 一.数学上的“嵌入”(Embedding) Embed这个词,英文的释义为, fi ...
- MSVC and MinGW DLLs
Posted February 26th, 2009 by earnie dll faq msvc TODO: Reformat to new wiki syntax. !!! [Minimalist ...
- Setting a maximum attachment size
By default IBM® Lotus® iNotes™ allows a maximum attachment size of 50,000K (50MB). You can increas ...
- 轻松解决vuejs跨域
Vuejs跨域问题实战 有时候,本地使用webpack开启一个node的dev端口,项目中使用vuejs去访问别人家的api,比如豆瓣或者其他的api,不使用jsonp肯定就会报跨域的问题. 如何让我 ...
- MVC4发布到IIS,出现HTTP 错误 404.0 - Not Found
web.config中添加 <system.webServer> <modules runAllManagedModulesForAllRequests="true&quo ...