前言
有时候跑单测,需要启动spring容器,但是不想启动xxl-job,这时候就希望有个配置来让我们控制是否启动xxl-job。
原文链接:https://blog.csdn.net/Baisitao_/article/details/126591176
原文作者:Sicimike
于是博主一通搜索,找到了这个issues。
https://gitee.com/xuxueli0323/xxl-job/issues/IOFA6
可以看到,可能作者觉得没有提供这个配置的必要,既然官方没提供类似的配置,那就自己开发一个吧。
环境
- spring-boot 2.1.2 RELEASE
- junit 4.12
- spring-boot-starter-test 2.1.2 RELEASE
- xxl-job-core 2.2.0
简读源码
简单的看了下xxl-job的源码,发现启动入口在com.xxl.job.core.executor.impl.XxlJobSpringExecutor#afterSingletonsInstantiated
这里,因为博主集成了spring,所以实际上是在Spring提供的钩子函数org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated
启动的xxl-job。如果没有集成spring,是在com.xxl.job.core.executor.XxlJobExecutor#start
启动,下面是XxlJobSpringExecutor#afterSingletonsInstantiated
的源码
@Override
public void afterSingletonsInstantiated() {
// init JobHandler Repository
/*initJobHandlerRepository(applicationContext);*/
// init JobHandler Repository (for method)
initJobHandlerMethodRepository(applicationContext);
// refresh GlueFactory
GlueFactory.refreshInstance(1);
// super start
try {
super.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
可以看到主要做了三件事
- 注册JobHandler
- 刷新GlueFactory
- 启动真正的
com.xxl.job.core.executor.XxlJobExecutor
由于作者没有预留相关的扩展点,所以只能自己想办法。大家在碰到类似场景的时候可以想想这句话。
没有什么是包一层不能解决的
这句话通俗易懂,实际上可以理解为代理。只要有了代理就可以为所欲为了。
实现
自定义类继承XxlJobSpringExecutor
我们可以自定义类来继承XxlJobSpringExecutor
,然后重写方法afterSingletonsInstantiated
public class SicimikeXxlJobSpringExecutor extends XxlJobSpringExecutor {
private static final Logger logger = LoggerFactory.getLogger(SicimikeXxlJobSpringExecutor.class);
@Override
public void afterSingletonsInstantiated() {
// 获取单测时设置的属性,可以自己定义属性名
// 不要问这个属性key怎么来的,后文单测时设置的
String xxlJobEnable = System.getProperty("sicimike.xxjob.enable");
if (Objects.equals(xxlJobEnable, "false")) {
// 如果设置了【不启动】xxljob,则直接跳过
logger.info("xxljob disable success .");
return;
}
// 如果没有设置,或者设置了启动xxljob,则调用父类的启动入口
super.afterSingletonsInstantiated();
}
}
修改配置
由于自定义类继承了XxlJobSpringExecutor
,所以配置的时候需要配置自定的类,用XML方式配置的同理
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
// 注意,这里实例化的是自定义的子类
XxlJobSpringExecutor xxlJobSpringExecutor = new SicimikeXxlJobSpringExecutor();
// 设置属性
// xxlJobSpringExecutor.setXxx
return xxlJobSpringExecutor;
}
单测使用
设置好了之后,在单测类中添加如下代码即可
@RunWith(SpringRunner.class)
@SpringBootTest
public class AaaServiceTest {
@BeforeClass
public static void before() {
// 单测不启动xxljob
// 注意属性key要和SicimikeXxlJobSpringExecutor中保持一致
System.setProperty("sicimike.xxjob.enable", "false");
}
@Autowired
private AaaService aaaService;
@Test
public void testAaa() {
aaaService.xxxx();
}
}
不出意外的话,启动单测会打出如下日志
2022-08-29 20:13:02.032 INFO 32094 --- [ main] com.sicimike.SicimikeXxlJobSpringExecutor 21 : xxljob disable success .
后记
可以看到,读源码并不是为了读而读,而是为了解决实际问题。并且并不一定需要修改源码才能达到目的,可以通过扩展的方式,这样也符合开闭原则。