根据选择实现的过程,预测具体的JAXP工厂实现会被加载是相当困难的,必须创建一个实例才能知道。以下是来自官方JAXP FAQ(第14个问题)的说明:
当应用程序想要创建一个新的JAXP DocumentBuilderFactory
实例时,它会调用静态方法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 JAR和Xalan)混合使用的情况:
DocumentBuilderFactory implementation: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jar
XPathFactory implementation: com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl loaded from: Java Runtime
TransformerFactory implementation: org.apache.xalan.processor.TransformerFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xalan.jar
SAXParserFactory implementation: org.apache.xerces.jaxp.SAXParserFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jar