最近一个项目使用listener 触发一个定时器轮询入库,可悲的发现执行类注入的javabean为null;google下来的方法不起作用,就来这里求大神帮忙了。
Timer timer = new Timer(true);
GrddSaveTask task = new GrddSaveTask();//这里由于listener早于servlet初始化,所以task注入参数为空。
timer.schedule(task, 1, 20);
如何在真正使用的时候,因为使用的时候spring已经启动了,给需要注入的Mng初始化。
或者如何子在一个非spring控制的类中获得当前环境中的spring Context。
Timer timer = new Timer(true);
GrddSaveTask task = new GrddSaveTask();//这里由于listener早于servlet初始化,所以task注入参数为空。
timer.schedule(task, 1, 20);
如何在真正使用的时候,因为使用的时候spring已经启动了,给需要注入的Mng初始化。
或者如何子在一个非spring控制的类中获得当前环境中的spring Context。
解决方案 »
- 一路走来,离开学校2月啦。。。遇到了一大堆问题,这不是最后一个
- ibatis多条件查询问题,急!急!急!!
- Servlet文件下载问题
- structs 全局跳转找不到路径问题
- 关于JDBC、Hibernate数据持久化的事务处理
- java 新手
- 项目外包:现场开发30天 JAVA,Hibernate+Spring+JasperReport 双倍于薪资的报酬
- jstl el ${}不能用怎么办?
- java 数据库提取大量数据生成txt文档,java内存总是溢出。。
- ***在线等***用j2ee的deploytool部署出下面错误怎么回事?
- 嵌入式tomcat如何设置maxPostSize参数
- 大虾帮帮忙java进
* 服务器启动关闭的监听器
* @version 1.0
*/
public class GlobalListener implements ServletContextListener {
private static final Logger log = LoggerFactory.getLogger(GlobalListener.class);
private Timer timer = new Timer(); /**
* 关闭服务器
*/
public void contextDestroyed(ServletContextEvent event) {
log.info("关闭服务器");
timer.cancel();
} /**
* 启动服务器
*/
public void contextInitialized(ServletContextEvent event) {
log.info("启动服务器");
FrameConfig.waterImgPath = "/common_res/images/water.jpg";
FrameConfig.maxCacheSize = 10000;
FrameConfig.encoding = "UTF-8";
timer.schedule(new TaskTimer(), getMillisecond(), Task.daySeconds * 1000l);// 每天执行一次
}
// 从现在到明天最早时间相差的毫秒数
private Long getMillisecond() {
DateUtil util = DateUtil.getBean();
String beginTime = util.getDetachDate(util.getNowDate(0) + " 00:00:00", 2, Task.daySeconds.intValue());
return util.getDateDiff(util.getNowDate(1), beginTime) * 1000l;
}}
/**
* 每天最早时间刷新客服回访任务的定时器
* @version 1.0
*/
public class TaskTimer extends TimerTask {
private static final Logger log = LoggerFactory.getLogger(TaskTimer.class); @Override
public void run() {
TaskMng mng = (TaskMng) BeanContainer.getBean(TaskMng.class);
Integer num = mng.renovate();
log.info("今天最早时间产生了" + num + "个客服回访任务");
CrmHistory.CRM_HISTORY_MAP = new HashMap<String, List<CrmHistory>>();
}}web.xml
<listener>
<listener-class>com.xxx.GlobalListener</listener-class>
</listener>
但是这种方式过渡依赖web容器,如果是单独类想用spring中的bean此方案不可用;
如果调用方也被spring配置管理,那可以用注解,get/set,构造器来获取spring中的其他bean
如果调用方既没有被spring管理,也没有和容器上下文有任何关系,想获取spring中的bean,只能借助BeanFactory工厂了,由工厂来为你创造,好多人就会想到用ClassPathXmlApplicationContext类似方式重新加载一遍spring配置构造一个ApplicationContext上下文或者一个工厂,岂不知这样做就会产生两个spring环境的上下文,另一个就是web端启动了一个spring环境上下文,我们如何只让spring的环境只启动一次呢?答案很简单,代码如下:
<bean id="serviceLocator" class="org.androidpn.server.service.ServiceLocator" scope="singleton" />
在spring的配置文件中配置一个serviceLocator,让web容器启动spring的时候将spring的上下文(也就是BeanFactory)传到我们定义的serviceLocator类中,代码如下:public class ServiceLocator implements BeanFactoryAware {
private static BeanFactory beanFactory = null; private static ServiceLocator servlocator = null; public void setBeanFactory(BeanFactory factory) throws BeansException {
this.beanFactory = factory;
} public BeanFactory getBeanFactory() {
return beanFactory;
} public static ServiceLocator getInstance() {
if (servlocator == null)
servlocator = (ServiceLocator) beanFactory.getBean("serviceLocator");
return servlocator;
}
/**
* 根据提供的bean名称得到相应的服务类
*
* @param servName
* bean名称
*/
public static Object getService(String servName) {
return beanFactory.getBean(servName);
}
}
这样在你的工程中任何地方想获取到spring上下文中的bean实例都可以通过ServiceLocator类来获得,堪称两全其美,内圣外王!!