在通过定义一个任务方法时,需要在任务方法被业务代码调用时,才触发后续的定时任务自动运行。
实现思路 1、首先看下源码spring提供的task是由一个注解@EnableScheduling来控制开关,所以源码从这里入手
通过源码,可以看到schdule的任务是由ScheduledAnnotationBeanPostProcessor来处理的,查看该类的源码可以得知:postProcessAfterInitialization(Object bean, String beanName)方法即为实际的任务注册
所以,接下来,就可以通过利用该方法。我们自定义选择注册时机,就可实现自定义时间开启此任务。
需要用到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 staticT 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(); }
运行结果:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)