做项目时经常需要有后台程序进行定期更新数据库的需要,一般做法都是定义一个listener,在应用启动时添加一个Timer,然后定期执行。而Timer需要传入一个继承TimerTask的线程类(姑且这么说吧),更新数据库的操作就写在这个类里,那么就需要在这个类里调用到service,Dao之类的东西,找了好久都没有找到解决方案。不是Hibernate的sessionFactory困扰,就是no session之类的错误,最后又想到如何获取到spring配置文件中sessionFactory。
获取spring配置中的sessionFactory这个方法是可以的,的确可以得到各种操作,但是会报Create an new Instance Cachemanager这个警告,似乎是重新实例化了一个HibernateSessionFactory的缓存管理器,而且最要命的是任务执行了10来次之后就会抛出通信异常,不知道何解。该方法被放弃了!
最后想到了把这个任务类也变成一个service,这样就可以通过spring管理自动注入相应同时还把该类注解成@Transactional纳入事务管理,并把需要操作的相关Dao也注解进来,这样就可以在run方法中得到引用,而且这个类也能通过spring的注入获取到了操作数据库的各种需要。
在listener通过spring工具类获取到这个任务类的Bean,只要把这个实例化的bean传给timer就OK了
timer = new java.util.Timer(true); event.getServletContext().log("定时任务已启动"); // 20秒扫描一次 需要执行的线程任务 延迟一分钟执行 SmsUtils sms = (SmsUtils) SpringBeanUtils.getBean("smsUtils", event.getServletContext()); timer.schedule(sms, 60 * 1000, 20 * 1000); event.getServletContext().log("短信发送任务已经添加调度表");
SpringBeanUtils.getBean方法中获取bean的方法
/** * 获取bean * * @param beanName * @param servletContext上下文 * @return */ public static Object getBean(String beanName, ServletContext servletContext) { ApplicationContext ctx = WebApplicationContextUtils .getWebApplicationContext(servletContext); return ctx.getBean(beanName); }
这个上下文可以在listener中获取,剩下的就等着任务循环的执行了!
不过这个方法会不会导致其他负面的影响尚不得知