强制子类将@Schedule添加到Java Spring中的超抽象类中的方法中

问题描述

我有一个超级抽象类,该类具有一些常见的实现方法和其他要由子类实现的抽象方法。常用的实现方法之一是被注释为@Scheduled的方法,但是我希望子类定义应如何定义此调度表(固定延迟,固定速率或cron等)。如何实现这种行为?

我想到的一种方法是重写要在子类中调度的方法,以便仅在超类中调用其对应的方法,并在其上添加@Scheduled并带有所需的定义,但我不这样做。不知道如何执行子类操作,因为该方法不是抽象

超级抽象类

public abstract class SuperClass {
       public void x();   // abstract method
       public void y() { 
              // Some implementation
       } 
    
       // Method to be scheduled. 
       public void scheduledMethod() {
              x();
              y();
       }
}

子类

public class Subclass extends SuperClass {
       public void x() { 
              // Some implementation
       }

       // How to enforce the developer to add this ? 
       @Scheduled(cron = "0 0 0 * * ?")
       public void scheduledMethod(){
              super.scheduledMethod()
       } 
}

解决方法

我无法理解如何使用@Scheduled,但是,我有另一种选择:

  1. 在您的抽象类中,要求子类实现一个方法以返回时间表:
public String getCronString();
  1. 使用子类中实现的方法getCronString()使用Scheduler以编程方式计划任务,以返回cron计划。很少有关于如何使用Spring Boot编程安排任务的示例:

基本上,如果您的子类未实现public String getCronString();,则您的代码将无法编译。

,

一种选择是在 bean 创建时检查 @Scheduled 注释是否存在(或 meta-present)。这可以通过在超类的 @PostConstruct 方法中使用反射轻松实现:

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;

public abstract class SuperClass {
    ...

    @PostConstruct
    public void enforceScheduling() {
        boolean annotationPresent = AnnotationUtils.getAnnotation(ClassUtils.getMethod(getClass(),"scheduledMethod"),Scheduled.class) != null;
        if (!annotationPresent) {
            throw new IllegalStateException("@Scheduled annotation missing from scheduledMethod");
        }
    }
}

当 Spring 尝试创建 bean 时,这将导致在应用程序启动时抛出异常,快速失败并且很明显缺少什么。

,

我过去在对类层次结构有约束的项目中做过的一件事是编写一个单元测试,该测试遍历类的每个具体(非抽象)实例并检查它是否满足该约束。

由于这是使用 Spring,我们可能更关心这种类型的每个 bean 是否匹配约束,而不是类路径上的每个子类是否匹配。

这种情况下的约束是在子类中的给定方法上存在 @Scheduled 注释(或 meta-present)。给定子类的 Class 对象,可以使用反射轻松实现注解的存在。

综合起来,我们可以使用这种技术编写单元测试:

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;

@SpringBootTest
public class SuperClassTest {
    @Autowired
    private List<SuperClass> beansOfThisType;

    @Test
    public void allBeansMustBeScheduled() {
        for (SuperClass bean : beansOfThisType) {
            boolean annotationPresent = AnnotationUtils.getAnnotation(ClassUtils.getMethod(bean.getClass(),Scheduled.class) != null;
            assertTrue(annotationPresent,"@Scheduled annotation missing from scheduledMethod for " + bean.getClass());
        }
    }
}

检查类路径上类型的每个对象而不仅仅是 Spring bean 是一种非常相似的方法;不同之处在于获取要检查的 Class 对象列表的机制。从类路径中获取匹配的对象不够直接,超出了本答案的范围。 How do you find all subclasses of a given class in Java? 列出了多种实现方式。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...