在本节,我们来分析一下jbpm的jbpmConfiguration类
我们生成jbpmConfiguration一般都是通过如下几个方法:
public static JbpmConfiguration getInstance() {
return getInstance(null);
}
public static JbpmConfiguration getInstance(String resource) {
JbpmConfiguration instance = null;
synchronized(instances) {
if (resource==null) {
resource = " jbpm.cfg.xml";
}
instance = (JbpmConfiguration) instances.get(resource);
if (instance==null) {
if (defaultObjectFactory!=null) {
log.debug("creating jbpm configuration from given default object factory
'"+defaultObjectFactory+"'");
instance = new JbpmConfiguration(defaultObjectFactory);
} else {
try {
log.info("using jbpm configuration resource '"+resource+"'");
InputStream jbpmCfgXmlStream = ClassLoaderUtil.getStream(resource);
if (jbpmCfgXmlStream==null)
throw new JbpmException("jbpm configuration resource '"+resource+"' is not
available");
ObjectFactory objectFactory = parseObjectFactory(jbpmCfgXmlStream);
instance = createJbpmConfiguration(objectFactory);
} catch (RuntimeException e) {
throw new JbpmException("couldn't parse jbpm configuration from resource
'"+resource+"'", e);
}
}
instances.put(resource, instance);
}
}
return instance;
}
从上面的三种方式,我们可以发现jbpmConfiguration是 一个不完全封闭的多例模式,他里面含有一个静
态的hashMap中,存储这JbpmConfiguration实例; 每一个实例都对应的是一个resource文件,也就是说一
个资源文件对应一个实例;
JbpmConfiguration实例还允许用户自己new实例化实例,并没有平常单例模式那样将其构造方法私有化,
允许了用户的自定义传入对象工厂;
下面我们来详细的了解一个其方法:
由下面这句我们知道newInstance的时候是 线程安全的
synchronized(instances)
下面这两句分别是得到这个资源文件的输入流,并且对他进行解析:
ObjectFactory objectFactory = parseObjectFactory(jbpmCfgXmlStream);
instance = createJbpmConfiguration(objectFactory);
解析资源文件得到一个ObjectFactory对象:
protected static ObjectFactory parseObjectFactory(InputStream inputStream) {
log.debug("loading defaults in jbpm configuration");
//构造解析的功能对象;
ObjectFactoryParser objectFactoryParser = new ObjectFactoryParser();
//对象工厂能够生产出对象;
ObjectFactoryImpl objectFactoryImpl = new ObjectFactoryImpl();
//会先解析org/jbpm/default.jbpm.cfg.xml的默认配置文件;
objectFactoryParser.parseElementsFromResource(" org/jbpm/default.jbpm.cfg.xml",
objectFactoryImpl);
if (inputStream!=null) {
//然后在解析子定义的文件;
objectFactoryParser.parseElementsStream(inputStream, objectFactoryImpl);
}
return objectFactoryImpl;
}
以下是对文件进行解析:
public void parseElements(Element element, ObjectFactoryImpl objectFactoryImpl) {
List objectInfoElements = XmlUtil.elements(element);
for (int i = 0; i<objectInfoElements.size(); i++) {
//遍历根元素下面的直接子元素;进行逐个解析
Element objectInfoElement = (Element) objectInfoElements.get(i);
ObjectInfo objectInfo = parse(objectInfoElement);
objectFactoryImpl.addObjectInfo(objectInfo);
}
}
public ObjectInfo parse(Element element) {
//被解析每一个子元素都是一个Bean的信息,他描述了这个bean的类型以及值;记住,只是类型
//对象工厂拿到这些bean类型能够生成bean对象;
ObjectInfo objectInfo = null;
String elementTagName = element.getTagName().toLowerCase();
// 这个地方是用反射来实例化beanInfo对象;
Constructor constructor = (Constructor) mappings.get(elementTagName);
if (constructor==null) {
throw new JbpmException("no ObjectInfo class specified for element
'"+elementTagName+"'");
}
try {
objectInfo = (ObjectInfo) constructor.newInstance(new Object[]{element,this});
} catch (Exception e) {
throw new JbpmException("couldn't parse '"+elementTagName+"' into a
'"+constructor.getDeclaringClass().getName()+"': "+XmlUtil.toString(element), e);
}
return objectInfo;
}
从下面这个mapping我们可以看出来:
if (defaultMappings==null) {
defaultMappings = new HashMap();
addMapping(defaultMappings, "bean", BeanInfo.class);
addMapping(defaultMappings, "ref", RefInfo.class);
addMapping(defaultMappings, "list", ListInfo.class);
addMapping(defaultMappings, "map", MapInfo.class);
addMapping(defaultMappings, "string", StringInfo.class);
addMapping(defaultMappings, "int", IntegerInfo.class);
addMapping(defaultMappings, "integer", IntegerInfo.class);
addMapping(defaultMappings, "long", LongInfo.class);
addMapping(defaultMappings, "float", FloatInfo.class);
addMapping(defaultMappings, "double", DoubleInfo.class);
addMapping(defaultMappings, "char", CharacterInfo.class);
addMapping(defaultMappings, "character", CharacterInfo.class);
addMapping(defaultMappings, "boolean", BooleanInfo.class);
addMapping(defaultMappings, "true", BooleanInfo.class);
addMapping(defaultMappings, "false", BooleanInfo.class);
addMapping(defaultMappings, "null", NullInfo.class);
addMapping(defaultMappings, "jbpm-context", JbpmContextInfo.class);
addMapping(defaultMappings, "jbpm-type", JbpmTypeObjectInfo.class);
}
能够根据这个tag名字找到实例化的构造函数,因为他们有同样参数的构造函数,这样就很好进行统一的
反射:
static void addMapping(Map mappings, String elementTagName, Class objectInfoClass) {
try {
Constructor constructor =
objectInfoClass.getDeclaredConstructor(constructorParameterTypes);
mappings.put(elementTagName, constructor);
} catch (Exception e) {
throw new JbpmException("couldn't add mapping for element '"+elementTagName+"':
constructor("+Element.class.getName()+","+ObjectFactoryParser.class.getName()+") was missing
for class '"+objectInfoClass.getName()+"'", e);
}
}
通过这样,我们可以看见如下的类图;
我们生成jbpmConfiguration一般都是通过如下几个方法:
public static JbpmConfiguration getInstance() {
return getInstance(null);
}
public static JbpmConfiguration getInstance(String resource) {
JbpmConfiguration instance = null;
synchronized(instances) {
if (resource==null) {
resource = " jbpm.cfg.xml";
}
instance = (JbpmConfiguration) instances.get(resource);
if (instance==null) {
if (defaultObjectFactory!=null) {
log.debug("creating jbpm configuration from given default object factory
'"+defaultObjectFactory+"'");
instance = new JbpmConfiguration(defaultObjectFactory);
} else {
try {
log.info("using jbpm configuration resource '"+resource+"'");
InputStream jbpmCfgXmlStream = ClassLoaderUtil.getStream(resource);
if (jbpmCfgXmlStream==null)
throw new JbpmException("jbpm configuration resource '"+resource+"' is not
available");
ObjectFactory objectFactory = parseObjectFactory(jbpmCfgXmlStream);
instance = createJbpmConfiguration(objectFactory);
} catch (RuntimeException e) {
throw new JbpmException("couldn't parse jbpm configuration from resource
'"+resource+"'", e);
}
}
instances.put(resource, instance);
}
}
return instance;
}
从上面的三种方式,我们可以发现jbpmConfiguration是 一个不完全封闭的多例模式,他里面含有一个静
态的hashMap中,存储这JbpmConfiguration实例; 每一个实例都对应的是一个resource文件,也就是说一
个资源文件对应一个实例;
JbpmConfiguration实例还允许用户自己new实例化实例,并没有平常单例模式那样将其构造方法私有化,
允许了用户的自定义传入对象工厂;
下面我们来详细的了解一个其方法:
由下面这句我们知道newInstance的时候是 线程安全的
synchronized(instances)
下面这两句分别是得到这个资源文件的输入流,并且对他进行解析:
ObjectFactory objectFactory = parseObjectFactory(jbpmCfgXmlStream);
instance = createJbpmConfiguration(objectFactory);
解析资源文件得到一个ObjectFactory对象:
protected static ObjectFactory parseObjectFactory(InputStream inputStream) {
log.debug("loading defaults in jbpm configuration");
//构造解析的功能对象;
ObjectFactoryParser objectFactoryParser = new ObjectFactoryParser();
//对象工厂能够生产出对象;
ObjectFactoryImpl objectFactoryImpl = new ObjectFactoryImpl();
//会先解析org/jbpm/default.jbpm.cfg.xml的默认配置文件;
objectFactoryParser.parseElementsFromResource(" org/jbpm/default.jbpm.cfg.xml",
objectFactoryImpl);
if (inputStream!=null) {
//然后在解析子定义的文件;
objectFactoryParser.parseElementsStream(inputStream, objectFactoryImpl);
}
return objectFactoryImpl;
}
以下是对文件进行解析:
public void parseElements(Element element, ObjectFactoryImpl objectFactoryImpl) {
List objectInfoElements = XmlUtil.elements(element);
for (int i = 0; i<objectInfoElements.size(); i++) {
//遍历根元素下面的直接子元素;进行逐个解析
Element objectInfoElement = (Element) objectInfoElements.get(i);
ObjectInfo objectInfo = parse(objectInfoElement);
objectFactoryImpl.addObjectInfo(objectInfo);
}
}
public ObjectInfo parse(Element element) {
//被解析每一个子元素都是一个Bean的信息,他描述了这个bean的类型以及值;记住,只是类型
//对象工厂拿到这些bean类型能够生成bean对象;
ObjectInfo objectInfo = null;
String elementTagName = element.getTagName().toLowerCase();
// 这个地方是用反射来实例化beanInfo对象;
Constructor constructor = (Constructor) mappings.get(elementTagName);
if (constructor==null) {
throw new JbpmException("no ObjectInfo class specified for element
'"+elementTagName+"'");
}
try {
objectInfo = (ObjectInfo) constructor.newInstance(new Object[]{element,this});
} catch (Exception e) {
throw new JbpmException("couldn't parse '"+elementTagName+"' into a
'"+constructor.getDeclaringClass().getName()+"': "+XmlUtil.toString(element), e);
}
return objectInfo;
}
从下面这个mapping我们可以看出来:
if (defaultMappings==null) {
defaultMappings = new HashMap();
addMapping(defaultMappings, "bean", BeanInfo.class);
addMapping(defaultMappings, "ref", RefInfo.class);
addMapping(defaultMappings, "list", ListInfo.class);
addMapping(defaultMappings, "map", MapInfo.class);
addMapping(defaultMappings, "string", StringInfo.class);
addMapping(defaultMappings, "int", IntegerInfo.class);
addMapping(defaultMappings, "integer", IntegerInfo.class);
addMapping(defaultMappings, "long", LongInfo.class);
addMapping(defaultMappings, "float", FloatInfo.class);
addMapping(defaultMappings, "double", DoubleInfo.class);
addMapping(defaultMappings, "char", CharacterInfo.class);
addMapping(defaultMappings, "character", CharacterInfo.class);
addMapping(defaultMappings, "boolean", BooleanInfo.class);
addMapping(defaultMappings, "true", BooleanInfo.class);
addMapping(defaultMappings, "false", BooleanInfo.class);
addMapping(defaultMappings, "null", NullInfo.class);
addMapping(defaultMappings, "jbpm-context", JbpmContextInfo.class);
addMapping(defaultMappings, "jbpm-type", JbpmTypeObjectInfo.class);
}
能够根据这个tag名字找到实例化的构造函数,因为他们有同样参数的构造函数,这样就很好进行统一的
反射:
static void addMapping(Map mappings, String elementTagName, Class objectInfoClass) {
try {
Constructor constructor =
objectInfoClass.getDeclaredConstructor(constructorParameterTypes);
mappings.put(elementTagName, constructor);
} catch (Exception e) {
throw new JbpmException("couldn't add mapping for element '"+elementTagName+"':
constructor("+Element.class.getName()+","+ObjectFactoryParser.class.getName()+") was missing
for class '"+objectInfoClass.getName()+"'", e);
}
}
通过这样,我们可以看见如下的类图;
![](https://p-blog.csdn.net/images/p_blog_csdn_net/turkeyzhou/EntryImages/20081121/configuration.png)