需要寫一個Job類,思路是利用Job執行個體初始化的時候啟動一個ScheduleExecutorTask,定時update一些東西。
@Component("RefreshJob")
public class RefreshJob{
@PostConstruct
public void start(){
logger.info("start()". + this);
ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1);
executor.scheduleAtFixedRate(new Runnable(){
public void run(){
try{
update();
}
catch(Exception exp){
}
}
}, 0, 1, TimeUnit.MINUTES);
}
Component本來是單例的,@PostConstruct是在執行個體化完成後調用的方法。但是日志中start()出現了兩次,并且this的位址不同,很明顯,RefreshJob執行個體化了兩次,造成兩個Job執行個體在同時運作。
求Google,結合兩篇文章的答案,分析得出:
web.xml中的DispatcherServlet繼承自ContextLoaderListener,兩者共用ApplicationContext,但是在啟動的時候,會分别調用initWebApplicationContext()方法,各自對@Component注解對象執行個體化一次,DispatcherServlet調用在後,在Controller中使用的是後面執行個體化的對象。
牛人A修改了Spring的源代碼解決之,但是後續影響未見其傳回。
文章中進一步解釋其執行個體化類的範圍不同,ContextLoaderListerner執行個體化DataSource/Dao/Service等其他Bean,DispatcherServlet初始化Controller/ViewResolver/HandlerMapping/HandlerAdapter相關web類。
但是不知為何@Component注解的類這兩次都不放過。
于是将@Component注解修改為@Service,日志中start()隻列印一次了,解決之。
參考文章:
http://www.cnblogs.com/mypm/p/3164737.html
http://blog.csdn.net/uyehgdhg/article/details/9463875