43
43
import org .springframework .beans .factory .BeanNameAware ;
44
44
import org .springframework .beans .factory .DisposableBean ;
45
45
import org .springframework .beans .factory .ListableBeanFactory ;
46
- import org .springframework .beans .factory .NoSuchBeanDefinitionException ;
47
- import org .springframework .beans .factory .NoUniqueBeanDefinitionException ;
48
46
import org .springframework .beans .factory .SmartInitializingSingleton ;
49
- import org .springframework .beans .factory .config .AutowireCapableBeanFactory ;
50
- import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
51
47
import org .springframework .beans .factory .config .DestructionAwareBeanPostProcessor ;
52
- import org .springframework .beans .factory .config .NamedBeanHolder ;
53
48
import org .springframework .beans .factory .support .MergedBeanDefinitionPostProcessor ;
54
49
import org .springframework .beans .factory .support .RootBeanDefinition ;
55
50
import org .springframework .context .ApplicationContext ;
71
66
import org .springframework .scheduling .config .ScheduledTask ;
72
67
import org .springframework .scheduling .config .ScheduledTaskHolder ;
73
68
import org .springframework .scheduling .config .ScheduledTaskRegistrar ;
69
+ import org .springframework .scheduling .config .TaskSchedulerRouter ;
74
70
import org .springframework .scheduling .support .CronTrigger ;
75
71
import org .springframework .scheduling .support .ScheduledMethodRunnable ;
76
72
import org .springframework .util .Assert ;
@@ -120,7 +116,7 @@ public class ScheduledAnnotationBeanPostProcessor
120
116
* in case of multiple scheduler beans found in the context.
121
117
* @since 4.2
122
118
*/
123
- public static final String DEFAULT_TASK_SCHEDULER_BEAN_NAME = "taskScheduler" ;
119
+ public static final String DEFAULT_TASK_SCHEDULER_BEAN_NAME = TaskSchedulerRouter . DEFAULT_TASK_SCHEDULER_BEAN_NAME ;
124
120
125
121
126
122
/**
@@ -254,6 +250,12 @@ private void finishRegistration() {
254
250
if (this .scheduler != null ) {
255
251
this .registrar .setScheduler (this .scheduler );
256
252
}
253
+ else {
254
+ TaskSchedulerRouter router = new TaskSchedulerRouter ();
255
+ router .setBeanName (this .beanName );
256
+ router .setBeanFactory (this .beanFactory );
257
+ this .registrar .setTaskScheduler (router );
258
+ }
257
259
258
260
if (this .beanFactory instanceof ListableBeanFactory lbf ) {
259
261
Map <String , SchedulingConfigurer > beans = lbf .getBeansOfType (SchedulingConfigurer .class );
@@ -264,91 +266,9 @@ private void finishRegistration() {
264
266
}
265
267
}
266
268
267
- if (this .registrar .hasTasks () && this .registrar .getScheduler () == null ) {
268
- Assert .state (this .beanFactory != null , "BeanFactory must be set to find scheduler by type" );
269
- try {
270
- // Search for TaskScheduler bean...
271
- this .registrar .setTaskScheduler (resolveSchedulerBean (this .beanFactory , TaskScheduler .class , false ));
272
- }
273
- catch (NoUniqueBeanDefinitionException ex ) {
274
- if (logger .isTraceEnabled ()) {
275
- logger .trace ("Could not find unique TaskScheduler bean - attempting to resolve by name: " +
276
- ex .getMessage ());
277
- }
278
- try {
279
- this .registrar .setTaskScheduler (resolveSchedulerBean (this .beanFactory , TaskScheduler .class , true ));
280
- }
281
- catch (NoSuchBeanDefinitionException ex2 ) {
282
- if (logger .isInfoEnabled ()) {
283
- logger .info ("More than one TaskScheduler bean exists within the context, and " +
284
- "none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
285
- "(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
286
- "ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
287
- ex .getBeanNamesFound ());
288
- }
289
- }
290
- }
291
- catch (NoSuchBeanDefinitionException ex ) {
292
- if (logger .isTraceEnabled ()) {
293
- logger .trace ("Could not find default TaskScheduler bean - attempting to find ScheduledExecutorService: " +
294
- ex .getMessage ());
295
- }
296
- // Search for ScheduledExecutorService bean next...
297
- try {
298
- this .registrar .setScheduler (resolveSchedulerBean (this .beanFactory , ScheduledExecutorService .class , false ));
299
- }
300
- catch (NoUniqueBeanDefinitionException ex2 ) {
301
- if (logger .isTraceEnabled ()) {
302
- logger .trace ("Could not find unique ScheduledExecutorService bean - attempting to resolve by name: " +
303
- ex2 .getMessage ());
304
- }
305
- try {
306
- this .registrar .setScheduler (resolveSchedulerBean (this .beanFactory , ScheduledExecutorService .class , true ));
307
- }
308
- catch (NoSuchBeanDefinitionException ex3 ) {
309
- if (logger .isInfoEnabled ()) {
310
- logger .info ("More than one ScheduledExecutorService bean exists within the context, and " +
311
- "none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
312
- "(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
313
- "ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
314
- ex2 .getBeanNamesFound ());
315
- }
316
- }
317
- }
318
- catch (NoSuchBeanDefinitionException ex2 ) {
319
- if (logger .isTraceEnabled ()) {
320
- logger .trace ("Could not find default ScheduledExecutorService bean - falling back to default: " +
321
- ex2 .getMessage ());
322
- }
323
- // Giving up -> falling back to default scheduler within the registrar...
324
- logger .info ("No TaskScheduler/ScheduledExecutorService bean found for scheduled processing" );
325
- }
326
- }
327
- }
328
-
329
269
this .registrar .afterPropertiesSet ();
330
270
}
331
271
332
- private <T > T resolveSchedulerBean (BeanFactory beanFactory , Class <T > schedulerType , boolean byName ) {
333
- if (byName ) {
334
- T scheduler = beanFactory .getBean (DEFAULT_TASK_SCHEDULER_BEAN_NAME , schedulerType );
335
- if (this .beanName != null && this .beanFactory instanceof ConfigurableBeanFactory cbf ) {
336
- cbf .registerDependentBean (DEFAULT_TASK_SCHEDULER_BEAN_NAME , this .beanName );
337
- }
338
- return scheduler ;
339
- }
340
- else if (beanFactory instanceof AutowireCapableBeanFactory acbf ) {
341
- NamedBeanHolder <T > holder = acbf .resolveNamedBean (schedulerType );
342
- if (this .beanName != null && beanFactory instanceof ConfigurableBeanFactory cbf ) {
343
- cbf .registerDependentBean (holder .getBeanName (), this .beanName );
344
- }
345
- return holder .getBeanInstance ();
346
- }
347
- else {
348
- return beanFactory .getBean (schedulerType );
349
- }
350
- }
351
-
352
272
353
273
@ Override
354
274
public void postProcessMergedBeanDefinition (RootBeanDefinition beanDefinition , Class <?> beanType , String beanName ) {
@@ -424,12 +344,11 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
424
344
* @param scheduled the {@code @Scheduled} annotation
425
345
* @param method the method that the annotation has been declared on
426
346
* @param bean the target bean instance
427
- * @see #createRunnable(Object, Method)
428
347
*/
429
348
private void processScheduledSync (Scheduled scheduled , Method method , Object bean ) {
430
349
Runnable task ;
431
350
try {
432
- task = createRunnable (bean , method );
351
+ task = createRunnable (bean , method , scheduled . scheduler () );
433
352
}
434
353
catch (IllegalArgumentException ex ) {
435
354
throw new IllegalStateException ("Could not create recurring task for @Scheduled method '" +
@@ -606,13 +525,31 @@ private void processScheduledTask(Scheduled scheduled, Runnable runnable, Method
606
525
* <p>The default implementation creates a {@link ScheduledMethodRunnable}.
607
526
* @param target the target bean instance
608
527
* @param method the scheduled method to call
609
- * @since 5.1
610
- * @see ScheduledMethodRunnable#ScheduledMethodRunnable(Object, Method)
528
+ * @since 6.1
611
529
*/
612
- protected Runnable createRunnable (Object target , Method method ) {
530
+ @ SuppressWarnings ("deprecation" )
531
+ protected Runnable createRunnable (Object target , Method method , @ Nullable String qualifier ) {
532
+ Runnable runnable = createRunnable (target , method );
533
+ if (runnable != null ) {
534
+ return runnable ;
535
+ }
613
536
Assert .isTrue (method .getParameterCount () == 0 , "Only no-arg methods may be annotated with @Scheduled" );
614
537
Method invocableMethod = AopUtils .selectInvocableMethod (method , target .getClass ());
615
- return new ScheduledMethodRunnable (target , invocableMethod , this .registrar ::getObservationRegistry );
538
+ return new ScheduledMethodRunnable (target , invocableMethod , qualifier , this .registrar ::getObservationRegistry );
539
+ }
540
+
541
+ /**
542
+ * Create a {@link Runnable} for the given bean instance,
543
+ * calling the specified scheduled method.
544
+ * @param target the target bean instance
545
+ * @param method the scheduled method to call
546
+ * @since 5.1
547
+ * @deprecated in favor of {@link #createRunnable(Object, Method, String)}
548
+ */
549
+ @ Deprecated (since = "6.1" )
550
+ @ Nullable
551
+ protected Runnable createRunnable (Object target , Method method ) {
552
+ return null ;
616
553
}
617
554
618
555
private static Duration toDuration (long value , TimeUnit timeUnit ) {
0 commit comments