版本:1.7.1
当定时任务类中无AOP切面,可以正常执行
AOP切面存在时候,无法正常执行
版本:1.7.1
当定时任务类中无AOP切面,可以正常执行
AOP切面存在时候,无法正常执行
1.8.0也存在这个问题 因为在执行器扫描的时候获取对象每个标注了JobExecutor对象的methods判断每个method中是否包含MapExecutor、ReduceExecutor、MergeReduceExecutor注解,由于AOP代理增强后method.getAnnotation(MapExecutor.class)无法获取到目标对象的注解导致的,解决办法可以重写一遍重新赋值,可以参考这个下面的类
/**
description: snailJob执行器重写
@author pangbh
@since 2025-09-29 16:14:36
*/
@Component
public class SnailJobExecutorRewrite {
private static final Set END_WITH_SET = new HashSet<>(Arrays.asList(
"AnnotationJobExecutor",
"AnnotationMapJobExecutor",
"AnnotationMapReduceJobExecutor"
));
// 存储需要使用 equals 判断的字符串
private static final Set EQUALS_SET = new HashSet<>(Arrays.asList(
"snailJobCMDJobExecutor",
"snailJobHttpExecutor",
"snailJobPowerShellJobExecutor",
"snailJobShellJobExecutor"
));
@EventListener(ApplicationReadyEvent.class)
public void mapExecutorRewrite() {
Field field = ReflectUtil.getField(JobExecutorInfoCache.class, "JOB_EXECUTOR_REPOSITORY");
ReflectUtil.setAccessible(field);
ConcurrentHashMap<String, JobExecutorInfo> repository = (ConcurrentHashMap<String, JobExecutorInfo>) ReflectUtil.getStaticFieldValue(field);
repository.values().forEach(executorInfo -> {
Object bean = executorInfo.getExecutor();
Class<?> beanClass = bean.getClass();
// 排除snailjob内部注解执行器
String executorName = executorInfo.getExecutorName();
for (String suffix : END_WITH_SET) {
if (executorName.endsWith(suffix)) {
return;
}
}
if (EQUALS_SET.contains(executorName)) {
return;
}
JobExecutor jobExecutor = AnnotationUtils.findAnnotation(beanClass, JobExecutor.class);
if (Objects.isNull(jobExecutor)) {
return;
}
List<Class<? extends JobArgs>> classes = Lists.newArrayList(ShardingJobArgs.class, JobArgs.class);
Method method = null;
for (Class<? extends JobArgs> clazz : classes) {
method = ReflectionUtils.findMethod(beanClass, jobExecutor.method(), clazz);
if (Objects.nonNull(method)) {
break;
}
}
if (method == null) {
method = ReflectionUtils.findMethod(beanClass, jobExecutor.method());
}
// 扫描MapExecutor、ReduceExecutor、MergeReduceExecutor注解
Map<String, Method> mapExecutorMethodMap = new HashMap<>();
Method reduceExecutor = null;
Method mergeReduceExecutor = null;
Method[] methods = ReflectionUtils.getDeclaredMethods(beanClass);
for (final Method method1 : methods) {
Class<?>[] parameterTypes = method1.getParameterTypes();
MapExecutor mapExecutor = AnnotationUtils.findAnnotation(method1, MapExecutor.class);
if (Objects.nonNull(mapExecutor)
&& parameterTypes.length > 0
&& parameterTypes[0].isAssignableFrom(MapArgs.class)) {
mapExecutorMethodMap.put(mapExecutor.taskName(), method1);
}
ReduceExecutor reduceExecutorAnno = AnnotationUtils.findAnnotation(method1, ReduceExecutor.class);
if (Objects.nonNull(reduceExecutorAnno)
&& parameterTypes.length > 0
&& parameterTypes[0].isAssignableFrom(ReduceArgs.class)) {
reduceExecutor = method1;
continue;
}
MergeReduceExecutor mergeReduceExecutorAnno = AnnotationUtils.findAnnotation(method1, MergeReduceExecutor.class);
if (Objects.nonNull(mergeReduceExecutorAnno)
&& parameterTypes.length > 0
&& parameterTypes[0].isAssignableFrom(MergeReduceArgs.class)) {
mergeReduceExecutor = method1;
}
}
JobExecutorInfo jobExecutorInfo = new JobExecutorInfo(executorInfo.getExecutorName(),
method, mapExecutorMethodMap, reduceExecutor, mergeReduceExecutor, bean
);
repository.put(executorInfo.getExecutorName(), jobExecutorInfo);
});
}
}