本章阅读收获:可了解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,如果我们有特定需求的话,也可以通过配置文件配置相应类名称进行加载注入,实现自己想要的效果。
结束语
又到了结束的日子,最近有点忙,所以小停了一段时间,加油,我们可以的~~~~~
网友评论