使用spring cloud[Dalston.SR1]版本开发定时job时,发现job执行了两次;
下面日志里发现一个job被一个任务调度池(task-scheduler)里的两个worker(task-scheduler-1 和 task-scheduler-2)执行,很奇怪;
2018-02-23 14:28:30.001 [task-scheduler-2] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==开始==
2018-02-23 14:28:30.002 [task-scheduler-2] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==结束==
2018-02-23 14:28:30.003 [task-scheduler-1] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==开始==
2018-02-23 14:28:30.003 [task-scheduler-1] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==结束==
在构造方法里加入log,确认了类只被加载了一次;
示例代码:
@RefreshScope
@Component
@EnableScheduling
public class ContractSealApplyJob{
@Value("${value1}")
private String value1;
/**
* 进行回调job
*/
@Scheduled(cron = "${0/30 * * * * *}")//每30秒
public void doCallBack(){
logger.info("==回调job==开始==");
....
logger.info("==回调job==结束==");
}
}
发现是spring cloud config 里的注解@RefreshScope导致;正确用法是把配置项放到一个Config类里面;然后在Job里注入。 @RefreshScope注解的类,在运行时刷新后,会重新生成一个新的实例;不过在上述Job里并未被重新实例化(没有刷新),而是把Job放入池里两次。
/**
* Convenience annotation to put a <code>@Bean</code> definition in
* {@link org.springframework.cloud.context.scope.refresh.RefreshScope refresh scope}.
* Beans annotated this way can be refreshed at runtime and any components that are using
* them will get a new instance on the next method call, fully initialized and injected
* with all dependencies.
*
* @author Dave Syer
*
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {
/**
* @see Scope#proxyMode()
*/
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
@RefreshScope还有别的坑,详见:http://www.cnblogs.com/yjmyzz/p/8085530.html