天天看点

SpringMVC开发@Component注解类被两次实例化问题分析与解决

  需要写一个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类。

SpringMVC开发@Component注解类被两次实例化问题分析与解决

但是不知为何@Component注解的类这两次都不放过。

于是将@Component注解修改为@Service,日志中start()只打印一次了,解决之。

参考文章:

http://www.cnblogs.com/mypm/p/3164737.html

http://blog.csdn.net/uyehgdhg/article/details/9463875