Spring Scheduled定义的方法调用时才开启此任务

Spring Scheduled定义的方法调用时才开启此任务,第1张

Spring Scheduled定义的方法调用时才开启此任务 来源

在通过定义一个任务方法时,需要在任务方法被业务代码调用时,才触发后续的定时任务自动运行。

实现思路 1、首先看下源码

spring提供的task是由一个注解@EnableScheduling来控制开关,所以源码从这里入手


通过源码,可以看到schdule的任务是由ScheduledAnnotationBeanPostProcessor来处理的,查看该类的源码可以得知:postProcessAfterInitialization(Object bean, String beanName)方法即为实际的任务注册

所以,接下来,就可以通过利用该方法。我们自定义选择注册时机,就可实现自定义时间开启此任务。

2、实现方法

需要用到spring的环境变量对象 ApplicationContext和bean工厂BeanFactory两个对象,而Spring提供方案只要实现自定义的Aware即可获取到全局的对象。如下我们需要编写一个工具类:

@Component
public class TestBeanFactory implements BeanFactoryAware, ApplicationContextAware {
    private static ConfigurableListableBeanFactory beanFactory=null;

    private static   ApplicationContext applicationContext=null;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException(
                    "AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        System.out.println("TestBeanFactory.setBeanFactory()");
        if (TestBeanFactory.beanFactory==null) {
            TestBeanFactory.beanFactory= (ConfigurableListableBeanFactory) beanFactory;
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("TestBeanFactory.setApplicationContext()");
        if (TestBeanFactory.applicationContext==null) {
            TestBeanFactory.applicationContext = applicationContext;
        }

    }
	
    public static  T getBean(Class c) {
        return applicationContext.getBean(c);
    }

    public static void registerBean(String name,Object object){
        beanFactory.registerSingleton(name,object);
    }
}

自定义一个类:
这里不需要加@Component注解,否则在项目启动时会自动注册类中定义的所有带@Scheduled注解的方法的

public class TestTask {

    private static boolean init=false;

    @Scheduled(cron = "0/3 * * * * ? ")
    public  void  task1(){
        if (!init){
            String baneName=TestTask.class.getName();
            TestTask task = new TestTask();
            TestBeanFactory.registerBean(baneName,task);
            // 利用spring帮我们完成注册
            ScheduledAnnotationBeanPostProcessor schedule = TestBeanFactory.getBean(ScheduledAnnotationBeanPostProcessor.class);
            schedule.postProcessAfterInitialization(task,baneName);
            init=true;
            System.out.println("注册任务成功...");
        }
        System.out.println("TestTask.task1()");

    }
}
测试

具体代码不写,只展示一个controller方法:

	@GetMapping("/start")
    public void test() {
       System.out.println("调用业务方法后...");
       new TestTask().task1();
    }

运行结果:

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5697670.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存