美文网首页
领略Quartz源码架构之美——源码实弹之Scheduler(三

领略Quartz源码架构之美——源码实弹之Scheduler(三

作者: 向光奔跑_ | 来源:发表于2018-11-26 20:02 被阅读0次

    本章阅读收获:可了解Quartz框架中的Scheduler部分源码

    继上一节内容

    上一节上我们讲到了StdSchedulerFactory.getScheduler()中的instantiate()方法中的参数初始化过程,下面我们继续来讲instantiate()这块后续内容。

    instantiate()后续源码讲解

    我们按照之前的源码阅读方式,逐步来进行分解突破。

     // If Proxying to remote scheduler, short-circuit here...
            //一般不调用
            // ~~~~~~~~~~~~~~~~~~
            if (rmiProxy) {
    
                if (autoId) {
                    schedInstId = DEFAULT_INSTANCE_ID;
                }
    
                String uid = (rmiBindName == null) ? QuartzSchedulerResources.getUniqueIdentifier(
                        schedName, schedInstId) : rmiBindName;
    
                RemoteScheduler remoteScheduler = new RemoteScheduler(uid, rmiHost, rmiPort);
    
                schedRep.bind(remoteScheduler);
    
                return remoteScheduler;
            }
    

    这个方法是用在rmi代理中的,我们在使用中基本不调用,所以我也没有深看(其实是因为我还太菜,过度钻入不好)。但其实是很有必要的,在扩展性上可以考虑更多。

    注 RMI:Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能简化远程接口对象的使用。

    之后代码是:

            // Create class load helper
            ClassLoadHelper loadHelper = null;
            try {
                loadHelper = (ClassLoadHelper) loadClass(classLoadHelperClass)
                        .newInstance();
            } catch (Exception e) {
                throw new SchedulerConfigException(
                        "Unable to instantiate class load helper class: "
                                + e.getMessage(), e);
            }
            //CascadingClassLoadHelper 初始化
            loadHelper.initialize();
    

    这里就开始初始化类加载器并且初始化。

    /**
         * 查询类加载器并加载类
         */
        private Class<?> loadClass(String className) throws ClassNotFoundException, SchedulerConfigException {
    
            try {
                ClassLoader cl = findClassloader();
                if(cl != null)
                    return cl.loadClass(className);
                throw new SchedulerConfigException("Unable to find a class loader on the current thread or class.");
            } catch (ClassNotFoundException e) {
                if(getClass().getClassLoader() != null)
                    return getClass().getClassLoader().loadClass(className);
                throw e;
            }
        }
    
        /**
         * 查询类加载器
         */
        private ClassLoader findClassloader() {
            // work-around set context loader for windows-service started jvms (QUARTZ-748)
            if(Thread.currentThread().getContextClassLoader() == null && getClass().getClassLoader() != null) {
                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
            }
            return Thread.currentThread().getContextClassLoader();
        }
    
        private String getSchedulerName() {
            return cfg.getStringProperty(PROP_SCHED_INSTANCE_NAME,
                    "QuartzScheduler");
        }
    

    可以看到我们这的类加载器是通过线程的上下文来进行获取的。这块代码也很一目了然,所以也不做太多介绍。

    而 loadHelper.initialize();这段代码是在执行初始化,这是个接口方法,实现方式根据子类不同而不通,我进去看了一个简单的实现类,里面其实就是空方法,所以主体流程上基本不设置也没什么关系。

            // If Proxying to remote JMX scheduler, short-circuit here...
            //一般不调用
            // ~~~~~~~~~~~~~~~~~~
            if (jmxProxy) {
                if (autoId) {
                    schedInstId = DEFAULT_INSTANCE_ID;
                }
    
                if (jmxProxyClass == null) {
                    throw new SchedulerConfigException("No JMX Proxy Scheduler class provided");
                }
    
                RemoteMBeanScheduler jmxScheduler = null;
                try {
                    jmxScheduler = (RemoteMBeanScheduler)loadHelper.loadClass(jmxProxyClass)
                            .newInstance();
                } catch (Exception e) {
                    throw new SchedulerConfigException(
                            "Unable to instantiate RemoteMBeanScheduler class.", e);
                }
    
                if (jmxObjectName == null) {
                    jmxObjectName = QuartzSchedulerResources.generateJMXObjectName(schedName, schedInstId);
                }
    
                jmxScheduler.setSchedulerObjectName(jmxObjectName);
    
                tProps = cfg.getPropertyGroup(PROP_SCHED_JMX_PROXY, true);
                try {
                    setBeanProps(jmxScheduler, tProps);
                } catch (Exception e) {
                    initException = new SchedulerException("RemoteMBeanScheduler class '"
                            + jmxProxyClass + "' props could not be configured.", e);
                    throw initException;
                }
    
                jmxScheduler.initialize();
    
                schedRep.bind(jmxScheduler);
    
                return jmxScheduler;
            }
    

    jmx基本正常流程下也不会用到,所以我们也不进行深度的展开。

    注:JMX(Java Management Extensions,即Java管理扩展)是Java平台上为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。

    可以看到虽然我们基本不怎么接触这个,但是框架的扩展性思路非常好。集成了JMX与RMI。

    //正常流程下的操作
            JobFactory jobFactory = null;
            //配置文件中是否指定jobFactory
            if(jobFactoryClass != null) {
                try {
                    jobFactory = (JobFactory) loadHelper.loadClass(jobFactoryClass)
                            .newInstance();
                } catch (Exception e) {
                    throw new SchedulerConfigException(
                            "Unable to instantiate JobFactory class: "
                                    + e.getMessage(), e);
                }
                //PROP_SCHED_JOB_FACTORY_PREFIX = org.quartz.scheduler.jobFactory
                tProps = cfg.getPropertyGroup(PROP_SCHED_JOB_FACTORY_PREFIX, true);
                try {
                    setBeanProps(jobFactory, tProps);
                } catch (Exception e) {
                    initException = new SchedulerException("JobFactory class '"
                            + jobFactoryClass + "' props could not be configured.", e);
                    throw initException;
                }
            }
    

    这个流程在干嘛呢?其实是如果配置文件中指定了jobFactory的类名称后,回去加载,并且获取配置参数,把它注入到jobFactory的bean中。

            InstanceIdGenerator instanceIdGenerator = null;
            //配置中不设置时跳过
            if(instanceIdGeneratorClass != null) {
                try {
                    instanceIdGenerator = (InstanceIdGenerator) loadHelper.loadClass(instanceIdGeneratorClass)
                        .newInstance();
                } catch (Exception e) {
                    throw new SchedulerConfigException(
                            "Unable to instantiate InstanceIdGenerator class: "
                            + e.getMessage(), e);
                }
    
                tProps = cfg.getPropertyGroup(PROP_SCHED_INSTANCE_ID_GENERATOR_PREFIX, true);
                try {
                    setBeanProps(instanceIdGenerator, tProps);
                } catch (Exception e) {
                    initException = new SchedulerException("InstanceIdGenerator class '"
                            + instanceIdGeneratorClass + "' props could not be configured.", e);
                    throw initException;
                }
            }
    

    相信大家也能一眼看出,根据这个类名就可以猜测出这是个自动生成标识ID的bean,如果我们有特定需求的话,也可以通过配置文件配置相应类名称进行加载注入,实现自己想要的效果。

    结束语

    又到了结束的日子,最近有点忙,所以小停了一段时间,加油,我们可以的~~~~~

    相关文章

      网友评论

          本文标题:领略Quartz源码架构之美——源码实弹之Scheduler(三

          本文链接:https://www.haomeiwen.com/subject/qoliqqtx.html