- Notifications
You must be signed in to change notification settings - Fork 38.9k
Closed
Labels
in: coreIssues in core modules (aop, beans, core, context, expression)Issues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancementA general enhancement
Milestone
Description
TaskDecorator doesn't directly work with task scheduler implementations - ThreadPoolTaskScheduler/ConcurrentTaskScheduler.
Related: #18502
I think the underlying reason is there is no easy way of applying TaskDecorator to ScheduledExecutorService.
Currently, I workaround by wrapping ScheduledExecutorService with a proxy that performs task decoration.
Proxy Handler:
publicclassTaskDecoratingScheduledExecutorServiceInterceptorimplementsMethodInterceptor{privatefinalTaskDecoratortaskDecorator; publicTaskDecoratingScheduledExecutorServiceInterceptor(TaskDecoratortaskDecorator){this.taskDecorator = taskDecorator} @OverridepublicObjectinvoke(MethodInvocationinvocation) throwsThrowable{Object[] args = invocation.getArguments(); if (args.length == 0){returninvocation.proceed(); // no decoration, simply proceed } Objectswapped; if (args[0] instanceofRunnable){swapped = replaceRunnable(method, (Runnable) args[0])} elseif (args[0] instanceofCallable){swapped = replaceCallable(method, (Callable) args[0])} elseif (args[0] instanceofCollection){// see the ExecutorService APIswapped = ((Collection<? extendsCallable<?>>) args[0]).stream() .map(callable -> replaceCallable(method, callable)) .collect(toList())} else{returninvocation.proceed(); // bail out, no replace needed } args[0] = swapped; // swapreturninvocation.proceed()} .... }Wrap created ScheduledThreadPoolExecutor in ThreadPoolTaskScheduler:
ThreadPoolTaskSchedulerscheduler = newThreadPoolTaskScheduler(){privateScheduledThreadPoolExecutorscheduledThreadPoolExecutor; @OverrideprotectedScheduledExecutorServicecreateExecutor(intpoolSize, ThreadFactorythreadFactory, RejectedExecutionHandlerrejectedExecutionHandler){// keep it for "getScheduledThreadPoolExecutor()"this.scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) super.createExecutor(poolSize, threadFactory, rejectedExecutionHandler); ScheduledExecutorServiceexecutorService = this.scheduledThreadPoolExecutor; // apply task decorator via proxyProxyFactoryproxyFactory = newProxyFactory(executorService); proxyFactory.addAdvice(newTaskDecoratingScheduledExecutorServiceInterceptor(taskDecorator)); return (ScheduledExecutorService) proxyFactory.getProxy()} @OverridepublicScheduledThreadPoolExecutorgetScheduledThreadPoolExecutor() throwsIllegalStateException{returnthis.scheduledThreadPoolExecutor} }I think it would be nice that ThreadPoolTaskScheduler/ConcurrentTaskScheduler to have some API to work with TaskDecorator OR a way to easily customize underlying ScheduledExecutorService to apply decorators.
For example, a delegate class that takes TaskDecorator:
publicclassTaskDecoratingScheduledExecutorServiceDelegateimplementScheduledExecutorService{privatefinalScheduledExecutorServicedelegate; privatefinalTaskDecoratortaskDecorator; ... }flozano, jsachania, scottmf, mcovmw, elvin-wong and 23 more
Metadata
Metadata
Assignees
Labels
in: coreIssues in core modules (aop, beans, core, context, expression)Issues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancementA general enhancement