在没有实际创建实例的情况下,很难预测将要加载哪些具体的JAXP工厂实现,因为选择实现的过程非常困难。
从官方JAXP常见问题解答(问题14)中:
当应用程序想要创建一个新的JAXP
documentBuilderFactory实例时,它将调用staic方法documentBuilderFactory.newInstance()。这将导致documentBuilderFactory使用以下顺序搜索具体子类的名称
:
- 系统属性的值,例如
javax.xml.parsers.documentBuilderFactory它是否存在并且可以访问。- 文件的内容(
$JAVA_HOME/jre/lib/jaxp.properties如果存在)。- Jar文件规范中指定的Jar服务提供者发现机制。jar文件可以具有一个资源(即嵌入式文件),例如
meta-INF/services/javax.xml.parsers.documentBuilderFactory包含要实例化的具体类的名称。- 后备平台的默认实现。
更复杂的是,每个JAXP工厂都可以指定一个独立的实现。通常使用一个解析器实现和另一个XSLT实现,但是上面选择机制的粒度使您可以更大程度地进行混合和匹配。
以下代码将输出有关四个主要JAXP工厂的信息:
private static void OutputJaxpImplementationInfo() { System.out.println(getJaxpImplementationInfo("documentBuilderFactory", documentBuilderFactory.newInstance().getClass())); System.out.println(getJaxpImplementationInfo("XPathFactory", XPathFactory.newInstance().getClass())); System.out.println(getJaxpImplementationInfo("TransformerFactory", TransformerFactory.newInstance().getClass())); System.out.println(getJaxpImplementationInfo("SAXParserFactory", SAXParserFactory.newInstance().getClass()));}private static String getJaxpImplementationInfo(String componentName, Class componentClass) { CodeSource source = componentClass.getProtectionDomain().getCodeSource(); return MessageFormat.format( "{0} implementation: {1} loaded from: {2}", componentName, componentClass.getName(), source == null ? "Java Runtime" : source.getLocation());}以下样本输出 说明了三种不同的JAXP实现(内置Xerces和Xerces 2.8和Xalan的外部JAR)的混合搭配:
documentBuilderFactory implementation: org.apache.xerces.jaxp.documentBuilderFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jarXPathFactory implementation: com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl loaded from: Java RuntimeTransformerFactory implementation: org.apache.xalan.processor.TransformerFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xalan.jarSAXParserFactory implementation: org.apache.xerces.jaxp.SAXParserFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jar



