SpringBoot AOP 切面与SnailJob的@MapExecutor存在冲突

Viewed 32

版本:1.7.1

当定时任务类中无AOP切面,可以正常执行
image.png
image.png

AOP切面存在时候,无法正常执行
image.png

1 Answers

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);
     });
    

    }
    }