quartzソース1-spring構成

21738 ワード

一つの任務job
1.1 jobDetail関連
1.1.1 JobDetailFactoryBean
jobインタフェースの実行タスククラスを継承する方法を指定してjobdetailを構成し、タスク実行時にjobインタフェースを介して実行タスクを呼び出す
ツールバーの
説明
String name;
jobDetail名
String group;
jobDetailグループ
Class> jobClass;
jobDetailが実行するタスククラス
JobDataMap jobDataMap
jobDetailの永続化データ
boolean durability
永続化するかどうか
boolean requestsRecovery
jobDetailがリカバリ可能かどうか
String description
jobDetailの説明
String beanName
jobDetailのbean名
ApplicationContext applicationContext;
bean容器
String applicationContextJobDataKey;
job呼び出しパラメータのbeanコンテナのkey値
JobDetail jobDetail;
前述のプロパティ初期化されたJobDetailImplの実際のオブジェクト
1.1.2 MethodInvokingJobDetailFactoryBean
  • ターゲットクラスを指定し、タスク実行方法によりjobdetailを構成し、タスク実行時に反射呼び出しによりタスク
  • を実行する.
  • prepare()ターゲットクラス、メソッド、パラメータに基づいて反射メソッドオブジェクトを初期化します.
  • 初期化タスク実行のjobインタフェース実装クラスjobClass
  • jdi.getJobDataMap().put("methodInvoker", this);タスク実行時にjobClassのmethodInvoker属性
  • を初期化する.
    public void afterPropertiesSet() throws ClassNotFoundException, NoSuchMethodException {
            this.prepare();
            String name = this.name != null?this.name:this.beanName;
            Class> jobClass = this.concurrent?MethodInvokingJobDetailFactoryBean.MethodInvokingJob.class:MethodInvokingJobDetailFactoryBean.StatefulMethodInvokingJob.class;
            JobDetailImpl jdi = new JobDetailImpl();
            jdi.setName(name);
            jdi.setGroup(this.group);
            jdi.setJobClass(jobClass);
            jdi.setDurability(true);
            jdi.getJobDataMap().put("methodInvoker", this);
            this.jobDetail = jdi;
            this.postProcessJobDetail(this.jobDetail);
        }
    
    public void prepare() throws ClassNotFoundException, NoSuchMethodException {
            String targetMethod;
            if(this.staticMethod != null) {
                int lastDotIndex = this.staticMethod.lastIndexOf(46);
                if(lastDotIndex == -1 || lastDotIndex == this.staticMethod.length()) {
                    throw new IllegalArgumentException("staticMethod must be a fully qualified class plus method name: e.g. 'example.MyExampleClass.myExampleMethod'");
                }
    
                targetMethod = this.staticMethod.substring(0, lastDotIndex);
                String methodName = this.staticMethod.substring(lastDotIndex + 1);
                this.targetClass = this.resolveClassName(targetMethod);
                this.targetMethod = methodName;
            }
    
            Class> targetClass = this.getTargetClass();
            targetMethod = this.getTargetMethod();
            Assert.notNull(targetClass, "Either 'targetClass' or 'targetObject' is required");
            Assert.notNull(targetMethod, "Property 'targetMethod' is required");
            Object[] arguments = this.getArguments();
            Class>[] argTypes = new Class[arguments.length];
    
            for(int i = 0; i < arguments.length; ++i) {
                argTypes[i] = arguments[i] != null?arguments[i].getClass():Object.class;
            }
    
            try {
                this.methodObject = targetClass.getMethod(targetMethod, argTypes);
            } catch (NoSuchMethodException var6) {
                this.methodObject = this.findMatchingMethod();
                if(this.methodObject == null) {
                    throw var6;
                }
            }
    
        }
    

    1.1.2.1タスクの実行
  • public static class MethodInvokingJob extends QuartzJobBeanタスクはQuartzJobBean
  • から継承されます.
  • QuartzJobBean担当属性注入private MethodInvoker methodInvoker;
  • タスク実行、反射呼び出しターゲットメソッドオブジェクト
  • protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
                context.setResult(this.methodInvoker.invoke());
            }
    
    public Object invoke() throws InvocationTargetException, IllegalAccessException {
            Object targetObject = this.getTargetObject();
            Method preparedMethod = this.getPreparedMethod();
            if(targetObject == null && !Modifier.isStatic(preparedMethod.getModifiers())) {
                throw new IllegalArgumentException("Target method must not be non-static without a target");
            } else {
                ReflectionUtils.makeAccessible(preparedMethod);
                return preparedMethod.invoke(targetObject, this.getArguments());
            }
        }
    

    1.2 jobFactory
    1.2.1 AdaptableJobFactory
  • で構成されたjobクラスで、runnableの場合はエージェントが作成されます.
  • で構成されたjobクラスは、jobインタフェース実装クラスは
  • に直接戻る.
  • その他のタイプは要求に合致せず、投げ異常
  • protected Job adaptJob(Object jobObject) throws Exception {
            if(jobObject instanceof Job) {
                return (Job)jobObject;
            } else if(jobObject instanceof Runnable) {
                return new DelegatingJob((Runnable)jobObject);
            } else {
                throw new IllegalArgumentException("Unable to execute job class [" + jobObject.getClass().getName() + "]: only [org.quartz.Job] and [java.lang.Runnable] supported.");
            }
        }
    

    1.2.2 SpringBeanJobFactory extends AdaptableJobFactory
  • 非QuartzJobBeanクラスはいくつかの属性注入の処理
  • を行う.
  • ignoredUnknownProperties構成は、jobクラスで書き込み不可であり、注入する必要がない属性を指定します.
  • protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Object job = super.createJobInstance(bundle);
            if(this.isEligibleForPropertyPopulation(job)) {
                BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
                MutablePropertyValues pvs = new MutablePropertyValues();
                if(this.schedulerContext != null) {
                    pvs.addPropertyValues(this.schedulerContext);
                }
    
                pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap());
                pvs.addPropertyValues(bundle.getTrigger().getJobDataMap());
                if(this.ignoredUnknownProperties != null) {
                    String[] var5 = this.ignoredUnknownProperties;
                    int var6 = var5.length;
    
                    for(int var7 = 0; var7 < var6; ++var7) {
                        String propName = var5[var7];
                        if(pvs.contains(propName) && !bw.isWritableProperty(propName)) {
                            pvs.removePropertyValue(propName);
                        }
                    }
    
                    bw.setPropertyValues(pvs);
                } else {
                    bw.setPropertyValues(pvs, true);
                }
            }
    
            return job;
        }
    

    1.3 job
    1.3.1 DelegatingJob
    エージェントrunnableのタスククラス
    1.3.2 QuartzJobBean
  • 属性注入を行う
  • public final void execute(JobExecutionContext context) throws JobExecutionException {
            try {
                BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
                MutablePropertyValues pvs = new MutablePropertyValues();
                pvs.addPropertyValues(context.getScheduler().getContext());
                pvs.addPropertyValues(context.getMergedJobDataMap());
                bw.setPropertyValues(pvs, true);
            } catch (SchedulerException var4) {
                throw new JobExecutionException(var4);
            }
    
            this.executeInternal(context);
        }
    

    にフリップフロップtrigger
    2.1 SimpleTriggerFactoryBean
  • サイクルトリガで、サイクル時間とトリガ回数を指定できます.

  • 2.1.1属性
    ツールバーの
    説明
    String name;
    trigger名
    String group;
    triggerパケット
    JobDetail jobDetail;
    trigger所属job情報
    JobDataMap jobDataMap
    job永続化データ
    Date startTime;
    開始時間
    long startDelay;
    どのくらい遅延してトリガーを開始しますか?
    long repeatInterval;
    繰り返しトリガの周期間隔
    int repeatCount = -1;
    繰り返し回数
    int priority;
    スケジューリング優先度
    int misfireInstruction;
    エラーポリシー
    String description
    説明情報
    String beanName;
    現在のbean名
    SimpleTrigger simpleTrigger;
    前述のプロパティを使用してSimpleTriggerImplを初期化
    2.1.2インタフェースの説明
  • public void afterPropertiesSet() bean初期化完了後に呼び出され、現在のbeanが実際に返されたオブジェクトとしてSimpleTriggerオブジェクトが初期化されます.
  •  public SimpleTrigger getObject() {
            return this.simpleTrigger;
        }
    
        public Class> getObjectType() {
            return SimpleTrigger.class;
        }
    

    2.2 CronTriggerFactoryBean
  • タイミングトリガ、cronルールに従ってタイミングトリガ.その他の構成は、周期トリガと同じ
  • ツールバーの
    説明
    String cronExpression
    タイミングルール
    CronTrigger cronTrigger;
    タイミングトリガ、CronTriggerImpl実装クラス
    3スケジューリングクラスSchedulerFactoryBean
  • FactoryBeanインタフェースは工場bean
  • を表す.
  • InitializingBeanインタフェースは、属性初期化が完了するとafterPropertiesSet()
  • が呼び出されることを示す.
  • SmartLifecycleインタフェースは、すべてのbean初期化が完了するとstart()
  • が呼び出されることを示す.
    3.1 afterPropertiesSet()
    3.1.1スケジューラ工場の初期化
    SchedulerFactory schedulerFactory = (SchedulerFactory)BeanUtils.instantiateClass(this.schedulerFactoryClass);
            this.initSchedulerFactory(schedulerFactory);
    
  • ユーザ構成に従ってスケジューラ工場((StdSchedulerFactory)schedulerFactory).initialize(mergedProps);
  • を初期化する.
    3.1.2スケジューラの作成
  • 初期化スレッドのクラスローダ
  • SchedulerRepository repositoryキャッシュ作成スケジューラ
  • synchronizedロック同時作成スケジューラ
  • を回避
    protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) throws SchedulerException {
            Thread currentThread = Thread.currentThread();
            ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
            boolean overrideClassLoader = this.resourceLoader != null && !this.resourceLoader.getClassLoader().equals(threadContextClassLoader);
            if(overrideClassLoader) {
                currentThread.setContextClassLoader(this.resourceLoader.getClassLoader());
            }
    
            Scheduler var10;
            try {
                SchedulerRepository repository = SchedulerRepository.getInstance();
                synchronized(repository) {
                    Scheduler existingScheduler = schedulerName != null?repository.lookup(schedulerName):null;
                    Scheduler newScheduler = schedulerFactory.getScheduler();
                    if(newScheduler == existingScheduler) {
                        throw new IllegalStateException("Active Scheduler of name '" + schedulerName + "' already registered in Quartz SchedulerRepository. Cannot create a new Spring-managed Scheduler of the same name!");
                    }
    
                    if(!this.exposeSchedulerInRepository) {
                        SchedulerRepository.getInstance().remove(newScheduler.getSchedulerName());
                    }
    
                    var10 = newScheduler;
                }
            } finally {
                if(overrideClassLoader) {
                    currentThread.setContextClassLoader(threadContextClassLoader);
                }
    
            }
    
            return var10;
        }
    
  • スケジューラ
  • の取得または作成
    public Scheduler getScheduler() throws SchedulerException {
            if (cfg == null) {
                initialize();
            }
    
            SchedulerRepository schedRep = SchedulerRepository.getInstance();
    
            Scheduler sched = schedRep.lookup(getSchedulerName());
    
            if (sched != null) {
                if (sched.isShutdown()) {
                    schedRep.remove(getSchedulerName());
                } else {
                    return sched;
                }
            }
    
            sched = instantiate();
    
            return sched;
        }
    

    3.1.2.1 StdSchedulerFactory.instantiate()
  • ユーザ構成変換
  • リモートスケジューラエージェント初期化RemoteScheduler
  • カスタムクラスローダインスタンス化loadHelper = (ClassLoadHelper) loadClass(classLoadHelperClass) .newInstance();
  • JMXリモートスケジューラ初期化
  • job工場類実例化jobFactory = (JobFactory) loadHelper.loadClass(jobFactoryClass) .newInstance();
  • idジェネレータinstanceIdGenerator = (InstanceIdGenerator) loadHelper.loadClass(instanceIdGeneratorClass) .newInstance();
  • を実例化する.
  • スレッドプールインスタンス化ThreadPool
  • データ永続化インスタンス化JobStore
  • データベース接続プールインスタンス化
  • プラグイン初期化
  • listener初期化
  • jobスレッドアクチュエータ初期化
  • jobコンテナファクトリ初期化
  • を実行
    JobRunShellFactory jrsf = null; // Create correct run-shell factory...
        
                if (userTXLocation != null) {
                    UserTransactionHelper.setUserTxLocation(userTXLocation);
                }
    if (wrapJobInTx) {
                    jrsf = new JTAJobRunShellFactory();
                } else {
                    jrsf = new JTAAnnotationAwareJobRunShellFactory();
                }
    
  • 上記スケジューラ関連リソースQuartzSchedulerResources
  • を組み立てる.
    QuartzSchedulerResources rsrcs = new QuartzSchedulerResources();
                rsrcs.setName(schedName);
                rsrcs.setThreadName(threadName);
                rsrcs.setInstanceId(schedInstId);
                rsrcs.setJobRunShellFactory(jrsf);
                rsrcs.setMakeSchedulerThreadDaemon(makeSchedulerThreadDaemon);
                rsrcs.setThreadsInheritInitializersClassLoadContext(threadsInheritInitalizersClassLoader);
                rsrcs.setBatchTimeWindow(batchTimeWindow);
                rsrcs.setMaxBatchSize(maxBatchSize);
                rsrcs.setInterruptJobsOnShutdown(interruptJobsOnShutdown);
                rsrcs.setInterruptJobsOnShutdownWithWait(interruptJobsOnShutdownWithWait);
                rsrcs.setJMXExport(jmxExport);
                rsrcs.setJMXObjectName(jmxObjectName);
    
                if (managementRESTServiceEnabled) {
                    ManagementRESTServiceConfiguration managementRESTServiceConfiguration = new ManagementRESTServiceConfiguration();
                    managementRESTServiceConfiguration.setBind(managementRESTServiceHostAndPort);
                    managementRESTServiceConfiguration.setEnabled(managementRESTServiceEnabled);
                    rsrcs.setManagementRESTServiceConfiguration(managementRESTServiceConfiguration);
                }
        
                if (rmiExport) {
                    rsrcs.setRMIRegistryHost(rmiHost);
                    rsrcs.setRMIRegistryPort(rmiPort);
                    rsrcs.setRMIServerPort(rmiServerPort);
                    rsrcs.setRMICreateRegistryStrategy(rmiCreateRegistry);
                    rsrcs.setRMIBindName(rmiBindName);
                }
        
                SchedulerDetailsSetter.setDetails(tp, schedName, schedInstId);
    
                rsrcs.setThreadExecutor(threadExecutor);
                threadExecutor.initialize();
    
                rsrcs.setThreadPool(tp);
                if(tp instanceof SimpleThreadPool) {
                    if(threadsInheritInitalizersClassLoader)
                        ((SimpleThreadPool)tp).setThreadsInheritContextClassLoaderOfInitializingThread(threadsInheritInitalizersClassLoader);
                }
                tp.initialize();
                tpInited = true;
        
                rsrcs.setJobStore(js);
        
                // add plugins
                for (int i = 0; i < plugins.length; i++) {
                    rsrcs.addSchedulerPlugin(plugins[i]);
                }
    
  • 初期化スケジューラqs = new QuartzScheduler(rsrcs, idleWaitTime, dbFailureRetry);
  • 初期化スケジューラエージェントScheduler scheduler = new StdScheduler(qs);
  • 各リソース初期化
  • スケジューリング初期化qs.initialize();詳細は、後続の文書
  • を参照してください.
    3.1.3スケジューラコンテキストの初期化
  • bean容器
  • ユーザ構成のschedulerContextMap
  • スケジューラを更新するjob工場
  • 3.1.4ユーザー構成のlistenerの登録
  • スケジューリングフローリスニングコールバック
  • jobステータスリスニングコールバック
  • triggerステータスリスニングコールバック
  • protected void registerListeners() throws SchedulerException {
            ListenerManager listenerManager = this.getScheduler().getListenerManager();
            int var3;
            int var4;
            if(this.schedulerListeners != null) {
                SchedulerListener[] var2 = this.schedulerListeners;
                var3 = var2.length;
    
                for(var4 = 0; var4 < var3; ++var4) {
                    SchedulerListener listener = var2[var4];
                    listenerManager.addSchedulerListener(listener);
                }
            }
    
            if(this.globalJobListeners != null) {
                JobListener[] var6 = this.globalJobListeners;
                var3 = var6.length;
    
                for(var4 = 0; var4 < var3; ++var4) {
                    JobListener listener = var6[var4];
                    listenerManager.addJobListener(listener);
                }
            }
    
            if(this.globalTriggerListeners != null) {
                TriggerListener[] var7 = this.globalTriggerListeners;
                var3 = var7.length;
    
                for(var4 = 0; var4 < var3; ++var4) {
                    TriggerListener listener = var7[var4];
                    listenerManager.addTriggerListener(listener);
                }
            }
    
        }
    

    3.1.5ユーザー構成のjobとtriggerを登録する
  • トランザクション方式統合追加構成jobとtrigger
  • 単独xml構成jobとtriggerの登録
  • job this.getScheduler().addJob(jobDetail, true);
  • を追加
  • trigger
  • を追加
    this.getScheduler().rescheduleJob(trigger.getKey(), trigger);
    this.getScheduler().scheduleJob(trigger);
    this.getScheduler().scheduleJob(jobDetail, trigger);
    
    protected void registerJobsAndTriggers() throws SchedulerException {
            TransactionStatus transactionStatus = null;
            if(this.transactionManager != null) {
                transactionStatus = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
            }
    
            try {
                if(this.jobSchedulingDataLocations != null) {
                    ClassLoadHelper clh = new ResourceLoaderClassLoadHelper(this.resourceLoader);
                    clh.initialize();
                    XMLSchedulingDataProcessor dataProcessor = new XMLSchedulingDataProcessor(clh);
                    String[] var4 = this.jobSchedulingDataLocations;
                    int var5 = var4.length;
    
                    for(int var6 = 0; var6 < var5; ++var6) {
                        String location = var4[var6];
                        dataProcessor.processFileAndScheduleJobs(location, this.getScheduler());
                    }
                }
    
                Iterator var10;
                if(this.jobDetails != null) {
                    var10 = this.jobDetails.iterator();
    
                    while(var10.hasNext()) {
                        JobDetail jobDetail = (JobDetail)var10.next();
                        this.addJobToScheduler(jobDetail);
                    }
                } else {
                    this.jobDetails = new LinkedList();
                }
    
                if(this.calendars != null) {
                    var10 = this.calendars.keySet().iterator();
    
                    while(var10.hasNext()) {
                        String calendarName = (String)var10.next();
                        Calendar calendar = (Calendar)this.calendars.get(calendarName);
                        this.getScheduler().addCalendar(calendarName, calendar, true, true);
                    }
                }
    
                if(this.triggers != null) {
                    var10 = this.triggers.iterator();
    
                    while(var10.hasNext()) {
                        Trigger trigger = (Trigger)var10.next();
                        this.addTriggerToScheduler(trigger);
                    }
                }
            } catch (Throwable var9) {
                if(transactionStatus != null) {
                    try {
                        this.transactionManager.rollback(transactionStatus);
                    } catch (TransactionException var8) {
                        this.logger.error("Job registration exception overridden by rollback exception", var9);
                        throw var8;
                    }
                }
    
                if(var9 instanceof SchedulerException) {
                    throw (SchedulerException)var9;
                }
    
                if(var9 instanceof Exception) {
                    throw new SchedulerException("Registration of jobs and triggers failed: " + var9.getMessage(), var9);
                }
    
                throw new SchedulerException("Registration of jobs and triggers failed: " + var9.getMessage());
            }
    
            if(transactionStatus != null) {
                this.transactionManager.commit(transactionStatus);
            }
    
        }
    

    3.2 start()
  • は遅延起動をサポートし、スケジューリングスレッドによってスケジューリング
  • を遅延する.
  • スケジューラstartインタフェース呼び出しscheduler.start();
  • protected void startScheduler(final Scheduler scheduler, final int startupDelay) throws SchedulerException {
            if(startupDelay <= 0) {
                this.logger.info("Starting Quartz Scheduler now");
                scheduler.start();
            } else {
                if(this.logger.isInfoEnabled()) {
                    this.logger.info("Will start Quartz Scheduler [" + scheduler.getSchedulerName() + "] in " + startupDelay + " seconds");
                }
    
                Thread schedulerThread = new Thread() {
                    public void run() {
                        try {
                            Thread.sleep((long)(startupDelay * 1000));
                        } catch (InterruptedException var3) {
                            ;
                        }
    
                        if(SchedulerFactoryBean.this.logger.isInfoEnabled()) {
                            SchedulerFactoryBean.this.logger.info("Starting Quartz Scheduler now, after delay of " + startupDelay + " seconds");
                        }
    
                        try {
                            scheduler.start();
                        } catch (SchedulerException var2) {
                            throw new SchedulingException("Could not start Quartz Scheduler after delay", var2);
                        }
                    }
                };
                schedulerThread.setName("Quartz Scheduler [" + scheduler.getSchedulerName() + "]");
                schedulerThread.setDaemon(true);
                schedulerThread.start();
            }
    
        }