복붙노트

[SPRING] 런타임시 스프링 <task : scheduled> 객체는 어떻게 표현됩니까?

SPRING

런타임시 스프링 객체는 어떻게 표현됩니까?

"task : scheduler"및 "task : scheduled-tasks"요소 ( "task : scheduled"요소가 포함 된 후자)를 사용하는 응용 프로그램이 있습니다. 이것은 모두 잘 작동합니다.

나는 "응용 프로그램 구성"을 내포하는 몇 가지 코드를 작성하여 어떤 중요한 작업에 대한 간단한 요약을 얻습니다.

나는 이미 "@Autowired"인스턴스 변수가있는 클래스를 가지고 있으므로이 모든 것을 반복 할 수 있습니다. 모든 TaskScheduler 객체를 가져 오는 "List"를 추가하는 것은 쉽습니다. 나는 이들 중 두 가지만 가지고 있으며, 나는 그들 각각에 서로 다른 일련의 작업을 가지고있다.

TaskScheduler 객체 (실제로는 ThreadPoolTaskScheduler 객체)에서 볼 수없는 것은 예약 된 작업 목록처럼 보이는 것이므로 예약 된 작업 목록은 다른 곳에 기록됩니다.

예약 된 작업 집합 및 해당 스레드 풀을 검사하는 데 사용할 수있는 개체는 무엇입니까?

해결법

  1. ==============================

    1.이 기능은 Spring 4.2에서 사용할 수 있습니다.

    이 기능은 Spring 4.2에서 사용할 수 있습니다.

    https://jira.spring.io/browse/SPR-12748 (면책 조항 :이 문제를보고했으며 솔루션에 대한 코드 제공).

    // Warning there may be more than one ScheduledTaskRegistrar in your
    // application context. If this is the case you can autowire a list of 
    // ScheduledTaskRegistrar instead.
    @Autowired   
    private ScheduledTaskRegistrar scheduledTaskRegistrar; 
    
    public List<Task> getScheduledTasks() {
        List<Task> result = new ArrayList<Task>();
        result.addAll(this.scheduledTaskRegistrar.getTriggerTaskList());
        result.addAll(this.scheduledTaskRegistrar.getCronTaskList());
        result.addAll(this.scheduledTaskRegistrar.getFixedRateTaskList());
        result.addAll(this.scheduledTaskRegistrar.getFixedDelayTaskList());
        return result;
    }
    
    // You can this inspect the tasks, 
    // so for example a cron task can be inspected like this:
    
    public List<CronTask> getScheduledCronTasks() {
        List<CronTask> cronTaskList = this.scheduledTaskRegistrar.getCronTaskList();
        for (CronTask cronTask : cronTaskList) {
            System.out.println(cronTask.getExpression);
        }
        return cronTaskList;
    }
    

    XML로 정의 된 ScheduledMethodRunnable을 사용하는 경우 :

    <task:scheduled method="run" cron="0 0 12 * * ?" ref="MyObject" />
    

    기본 대상 객체에 액세스 할 수 있습니다.

     ScheduledMethodRunnable scheduledMethodRunnable = (ScheduledMethodRunnable) task.getRunnable();
     TargetClass target = (TargetClass) scheduledMethodRunnable.getTarget();
    
  2. ==============================

    2.내가 아직 출시 후보 레벨에 앉아 있기 때문에 나는 봄 4.2에 대한 발췌 문장을 가지고있다.

    내가 아직 출시 후보 레벨에 앉아 있기 때문에 나는 봄 4.2에 대한 발췌 문장을 가지고있다.

    scheduledFuture 인터페이스는 BlockingQueue의 모든 실행 가능 요소에 의해 구현됩니다.

            Map<String, ThreadPoolTaskScheduler> schedulers = applicationContext
                    .getBeansOfType(ThreadPoolTaskScheduler.class);
            for (ThreadPoolTaskScheduler scheduler : schedulers.values()) {
                ScheduledExecutorService exec = scheduler.getScheduledExecutor();
                ScheduledThreadPoolExecutor poolExec = scheduler
                        .getScheduledThreadPoolExecutor();
                BlockingQueue<Runnable> queue = poolExec.getQueue();
                Iterator<Runnable> iter = queue.iterator();
                while (iter.hasNext()) {
                    ScheduledFuture<?> future = (ScheduledFuture<?>) iter.next();
                    future.getDelay(TimeUnit.MINUTES);
                Runnable job = iter.next();
                logger.debug(MessageFormat.format(":: Task Class is {0}", JobDiscoverer.findRealTask(job)));
                }
    

    ThreadPool Name Prefix가 나에게 별개의 이름을 반환하지 않았기 때문에 어떤 작업 클래스가 풀에 있는지에 대한 정보를 얻을 수있는 반성 방법은 다음과 같습니다.

    public class JobDiscoverer {
        private final static Field syncInFutureTask;
        private final static Field callableInFutureTask;
        private static final Class<? extends Callable> adapterClass;
        private static final Field runnableInAdapter;
        private static Field reschedulingRunnable;
        private static Field targetScheduledMethod;
    
        static {
            try {
    
                reschedulingRunnable = Class
                        .forName(
                                "org.springframework.scheduling.support.DelegatingErrorHandlingRunnable")
                        .getDeclaredField("delegate");
                reschedulingRunnable.setAccessible(true);
    
                targetScheduledMethod = Class
                        .forName(
                                "org.springframework.scheduling.support.ScheduledMethodRunnable")
                        .getDeclaredField("target");
                targetScheduledMethod.setAccessible(true);
                callableInFutureTask = Class.forName(
                        "java.util.concurrent.FutureTask$Sync").getDeclaredField(
                        "callable");
                callableInFutureTask.setAccessible(true);
                syncInFutureTask = FutureTask.class.getDeclaredField("sync");
                syncInFutureTask.setAccessible(true);
    
                adapterClass = Executors.callable(new Runnable() {
                    public void run() {
                    }
                }).getClass();
                runnableInAdapter = adapterClass.getDeclaredField("task");
                runnableInAdapter.setAccessible(true);
            } catch (NoSuchFieldException e) {
                throw new ExceptionInInitializerError(e);
            } catch (SecurityException e) {
                throw new PiaRuntimeException(e);
            } catch (ClassNotFoundException e) {
                throw new PiaRuntimeException(e);
            }
        }
    
        public static Object findRealTask(Runnable task) {
            if (task instanceof FutureTask) {
                try {
                    Object syncAble = syncInFutureTask.get(task);
                    Object callable = callableInFutureTask.get(syncAble);
                    if (adapterClass.isInstance(callable)) {
                        Object reschedulable = runnableInAdapter.get(callable);
                        Object targetable = reschedulingRunnable.get(reschedulable);
                        return targetScheduledMethod.get(targetable);
                    } else {
                        return callable;
                    }
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException(e);
                }
            }
            throw new ClassCastException("Not a FutureTask");
        }
    
  3. ==============================

    3.@Scheduled 기반 구성을 사용하면 Tobias M의 대답에서 얻은 접근 방식이 즉시 사용할 수 없습니다.

    @Scheduled 기반 구성을 사용하면 Tobias M의 대답에서 얻은 접근 방식이 즉시 사용할 수 없습니다.

    주석 기반 구성에는 사용할 수없는 ScheduledTaskRegistrar 인스턴스를 autowiring하는 대신 getScheduledTasks () 메소드 만있는 ScheduledTaskHolder를 자동으로 대신 사용할 수 있습니다.

    배경:

    @Scheduled 작업을 관리하는 데 사용되는 ScheduledAnnotationBeanPostProcessor는 내부 ScheduledTaskRegistrar를 가지며 Bean으로 사용할 수 없습니다. 하지만 ScheduledTaskHolder를 구현합니다.

  4. ==============================

    4.모든 Spring XML 엘리먼트에는 상응하는 BeanDefinitionReader가있다. 의 경우 ScheduledTasksBeanDefinitionParser입니다.

    모든 Spring XML 엘리먼트에는 상응하는 BeanDefinitionReader가있다. 의 경우 ScheduledTasksBeanDefinitionParser입니다.

    이 메소드는 BeanDefinitionBuilder를 사용하여 ContextLifecycleScheduledTaskRegistrar 유형의 bean에 대한 BeanDefinition을 작성합니다. 예약 된 작업은 해당 빈에 저장됩니다.

    작업은 기본 TaskScheduler 또는 제공 한 TaskScheduler에서 실행됩니다.

    클래스 이름을 제공 했으므로 세부적인 세부적인 내용이 필요하면 소스 코드를 직접 볼 수 있습니다.

  5. from https://stackoverflow.com/questions/21791853/how-are-spring-taskscheduled-objects-represented-at-runtime by cc-by-sa and MIT license