重写Spring的Scheduled来实现定时任务的开关功能

1 概述

项目中一般都会有定时任务的相关案例,那么我们一般会通过java提供的ScheduledExecutorService 或Spring提供的TaskScheduler(也可使用@Scheduled注解)来实现,因为其不需要依赖外部模块,简单实用,但是Spring提供的@Scheduled注解的定时任务并不支持任务的动态开启与关闭,以及排期的动态修改,本案例通过重写Spring的定时任务注解@Scheduled 来使其可以支持应用服务不停止的情况下在线动态修改任务的排期以及启停功能。

案例代码地址:https://github.com/AIFEINIK/Spring-Scheduled

2 重写Scheduled

2.1 自定义JobScheduled注解

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface JobScheduled {
    /**
     * cron 表达式
     * @return
     */
    String cron() default "";

    /**
     * 时区
     * @return
     */
    String zone() default "";

    /**
     * 是否开启任务,默认开启
     * @return
     */
    String enable() default "true";

    /**
     * 下次任务执行时间与上次执行任务之间固定间隔毫秒数
     * @return
     */
    long fixedDelay() default -1;

    String fixedDelayString() default "";

    /**
     * 以固定速率执行任务
     * @return
     */
    long fixedRate() default -1;

    String fixedRateString() default "";

    /**
     * 初始延迟时间,毫秒
     * @return
     */
    long initialDelay() default -1;

    String initialDelayString() default "";
}

2.2 自定义注解JobScheduled的解析器类

@Component
public class JobScheduledAnnotationBeanPostProcessor
        implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanNameAware,
        BeanFactoryAware, ApplicationContextAware, SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private DataConfig config;

    @Nullable
    private Object scheduler;

    @Nullable
    private StringValueResolver embeddedValueResolver;

    @Nullable
    private BeanFactory beanFactory;

    @Nullable
    private String beanName;

    private boolean init = true;

    @Nullable
    private ApplicationContext applicationContext;

    public Map<String, Object> beanMap = new HashMap<>();

    private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();

    private final Set<Class<?>> nonAnnotatedClasses = Collections.newSetFromMap(new ConcurrentHashMap<>(64));

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.embeddedValueResolver = resolver;
    }

    @Override
    public int getOrder() {
        return LOWEST_PRECEDENCE;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        if (this.beanFactory == null) {
            this.beanFactory = applicationContext;
        }
    }

    @Nullable
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return getObject(bean);
    }

    public Object getObject(Object bean) {
        Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
        if (!this.nonAnnotatedClasses.contains(targetClass)) {
            final Set<Method> annotatedMethods = new LinkedHashSet<>(1);
            ReflectionUtils.doWithMethods(targetClass, method -> {
                Set<JobScheduled> schedules = AnnotationUtils.getRepeatableAnnotations(method, JobScheduled.class, Schedules.class);
                for (JobScheduled jobScheduled : schedules) {
                    processScheduled(jobScheduled, method, bean);
                    annotatedMethods.add(method);
              
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值