feat(executor): 新增任务扫描排除路径配置

- 在执行器中新增 excludedPackage 配置项,支持指定包路径下的 Bean 在任务扫描时被忽略
- 支持配置多个包路径,使用逗号分隔
- 优化任务扫描逻辑,跳过懒加载和排除包中的 Bean
- 完善日志输出,提升调试与维护效率
- 更新示例项目
pull/72/head
xuxueli 3 months ago
parent 0f994a6f21
commit e19e33e8ed

@ -981,6 +981,8 @@ xxl.job.executor.port=9999
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 执行器日志文件保存天数 [选填] 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
xxl.job.executor.logretentiondays=30
### 任务扫描排除路径任务扫描时忽略指定包路径下的Bean支持配置多个包路径、逗号分隔
xxl.job.executor.excludedpackage=org.springframework,spring
```
#### 步骤三:执行器组件配置
@ -2581,10 +2583,11 @@ public void execute() {
- 9、【优化】调度不重不漏逻辑优化调度时间轮单刻度数据去重避免极端情况下任务重复执行时间轮转动时校验临近刻度避免极端情况下遗漏刻度
- 10、【重构】调度过期策略、调度类型策略逻辑重构代码组件化拆分并完善日志提升健壮性及可维护性
- 11、【优化】执行器任务Bean扫描逻辑优化完善懒加载Bean检测及过滤机制
- 12、【ING】UI框架重构升级提升交互体验
- 13、【ING】调整资源加载逻辑移除不必要的拦截器逻辑提升页面加载效率
- 14、【ING】规范API交互协议通用响应结构体调整为Response
- 15、【ING】Http通讯组件升级基于接口代理方式重构
- 12、【新增】执行器新增“任务扫描排除路径”配置项(xxl.job.executor.excludedpackage)任务扫描时忽略指定包路径下的Bean支持配置多个包路径、逗号分隔
- 13、【ING】UI框架重构升级提升交互体验
- 14、【ING】调整资源加载逻辑移除不必要的拦截器逻辑提升页面加载效率
- 15、【ING】规范API交互协议通用响应结构体调整为Response
- 16、【ING】Http通讯组件升级基于接口代理方式重构
### TODO LIST

@ -167,7 +167,7 @@ public class JobInfoController {
}
}
} catch (Exception e) {
logger.error("nextTriggerTime error. scheduleType = {}, scheduleConf= {}", scheduleType, scheduleConf, e);
logger.error(">>>>>>>>>>> nextTriggerTime error. scheduleType = {}, scheduleConf= {}", scheduleType, scheduleConf, e);
return ReturnT.ofFail((I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) + e.getMessage());
}
return ReturnT.ofSuccess(result);

@ -28,7 +28,7 @@ import java.util.concurrent.ConcurrentMap;
public class XxlJobExecutor {
private static final Logger logger = LoggerFactory.getLogger(XxlJobExecutor.class);
// ---------------------- param ----------------------
// ---------------------- field ----------------------
private String adminAddresses;
private String accessToken;
private int timeout;

@ -9,13 +9,15 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.annotation.AnnotatedElementUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -27,6 +29,17 @@ import java.util.Map;
public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(XxlJobSpringExecutor.class);
// ---------------------- field ----------------------
/**
* excluded package, like "org.springframework""org.aaa,org.bbb"
*/
private String excludedPackage = "org.springframework.,spring.";
public void setExcludedPackage(String excludedPackage) {
this.excludedPackage = excludedPackage;
}
// ---------------------- start / stop ----------------------
@ -54,50 +67,76 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
super.destroy();
}
/**
* check bean if excluded
*
* @param excludedPackageList excludedPackageList
* @param beanClassName beanClassName
* @return true if excluded
*/
private boolean isExcluded(List<String> excludedPackageList, String beanClassName) {
if (excludedPackageList == null || excludedPackageList.isEmpty() || beanClassName==null) {
return false;
}
for (String excludedPackage : excludedPackageList) {
if (beanClassName.startsWith(excludedPackage)) {
return true;
}
}
return false;
}
/**
* init job handler from method
*
* @param applicationContext applicationContext
*/
private void initJobHandlerMethodRepository(ApplicationContext applicationContext) {
// valid
if (applicationContext == null) {
return;
}
// build excluded package list
List<String> excludedPackageList = new ArrayList<>();
if (excludedPackage != null) {
for (String excludedPackage : excludedPackage.split(",")) {
if (!excludedPackage.trim().isEmpty()){
excludedPackageList.add(excludedPackage.trim());
}
}
}
// init job handler from method
String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, false); // allowEagerInit=false, avoid early initialization
for (String beanDefinitionName : beanDefinitionNames) {
// skip system bean
if (isSystemBean(beanDefinitionName)) {
continue;
}
// analyse BeanDefinition
if (applicationContext instanceof BeanDefinitionRegistry beanDefinitionRegistry) {
// get BeanDefinition
if (!beanDefinitionRegistry.containsBeanDefinition(beanDefinitionName)) {
continue;
}
BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanDefinitionName);
// skip lazy bean
if (applicationContext instanceof GenericApplicationContext genericApplicationContext) {
if (!genericApplicationContext.containsBeanDefinition(beanDefinitionName)) {
// skip excluded bean
String beanClassName = beanDefinition.getBeanClassName();
if (isExcluded(excludedPackageList, beanClassName)) {
logger.debug(">>>>>>>>>>> xxl-job bean-definition scan, skip excluded-package beanDefinitionName:{}, beanClassName:{}", beanDefinitionName, beanClassName);
continue;
}
// valid lazy bean
BeanDefinition beanDefinition = genericApplicationContext.getBeanDefinition(beanDefinitionName);
// skip lazy bean
if (beanDefinition.isLazyInit()) {
logger.debug("xxl-job bean-definition scan, skip lazy-init bean:{}", beanDefinitionName);
logger.debug(">>>>>>>>>>> xxl-job bean-definition scan, skip lazy-init beanDefinitionName:{}", beanDefinitionName);
continue;
}
}
// load bean
Object bean = applicationContext.getBean(beanDefinitionName);
/*
skip lazy bean2
Object bean = null;
Lazy onBean = applicationContext.findAnnotationOnBean(beanDefinitionName, Lazy.class);
if (onBean!=null){
logger.debug("xxl-job annotation scan, skip @Lazy Bean:{}", beanDefinitionName);
continue;
}else {
bean = applicationContext.getBean(beanDefinitionName);
}
*/
// filter method
Map<Method, XxlJob> annotatedMethods = null; // referred to org.springframework.context.event.EventListenerMethodProcessor.processBean
@ -127,12 +166,6 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
}
}
// check if system bean, not job bean
private boolean isSystemBean(String beanClassName) {
return beanClassName.startsWith("org.springframework")
|| beanClassName.startsWith("spring.");
}
// ---------------------- applicationContext ----------------------
private static ApplicationContext applicationContext;

@ -43,6 +43,9 @@ public class XxlJobConfig {
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Value("${xxl.job.executor.excludedpackage}")
private String excludedPackage;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
@ -57,6 +60,7 @@ public class XxlJobConfig {
xxlJobSpringExecutor.setTimeout(timeout);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
xxlJobSpringExecutor.setExcludedPackage(excludedPackage);
return xxlJobSpringExecutor;
}

@ -25,3 +25,5 @@ xxl.job.executor.port=9999
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job executor log-retention-days
xxl.job.executor.logretentiondays=30
### xxl-job executor excluded package, will skip when scan job. for example: org.springframework.,spring.
xxl.job.executor.excludedpackage=org.springframework,spring

Loading…
Cancel
Save