Replace XMLReaderFactory with SAXParserFactory

XMLReaderFactory has been marked as deprecated and without additional
configuration, and it's slower than SAXParserFactory.

Previously `XMLReaderFactory.createXMLReader()` is called upon every
request. This is an anti-pattern as mentioned in [1] and it can be very
slow since it loads the jar service file unless a parser has been
pre-assigned [2] (e.g. by setting org.xml.sax.driver).

SAXParserFactory uses a FactoryFinder [3] instead, which takes advantage
of a thread-local cache provided by ServiceLoader. Developers can still
pre-assign a factory by setting javax.xml.parsers.SAXParserFactory to
make it faster.

[1] https://bugs.openjdk.java.net/browse/JDK-6925410
[2] c8add223a1/src/java.xml/share/classes/org/xml/sax/helpers/XMLReaderFactory.java (L144-L148)
[3] 66c653c561/src/java.xml/share/classes/javax/xml/parsers/SAXParserFactory.java (L181-L185)

See gh-27239
This commit is contained in:
Frederick Zhang
2021-08-04 17:15:18 +10:00
committed by Stephane Nicoll
parent 32359c52b4
commit baed0785fd
8 changed files with 71 additions and 34 deletions

View File

@@ -21,6 +21,8 @@ import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Result;
import javax.xml.transform.dom.DOMResult;
@@ -63,9 +65,11 @@ abstract class AbstractStaxHandlerTests {
@BeforeEach
@SuppressWarnings("deprecation") // on JDK 9
void createXMLReader() throws Exception {
xmlReader = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true);
SAXParser saxParser = saxParserFactory.newSAXParser();
xmlReader = saxParser.getXMLReader();
xmlReader.setEntityResolver((publicId, systemId) -> new InputSource(new StringReader("")));
}

View File

@@ -19,6 +19,8 @@ package org.springframework.util.xml;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Transformer;
@@ -64,10 +66,12 @@ abstract class AbstractStaxXMLReaderTests {
@BeforeEach
@SuppressWarnings("deprecation") // on JDK 9
void setUp() throws Exception {
inputFactory = XMLInputFactory.newInstance();
standardReader = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true);
SAXParser saxParser = saxParserFactory.newSAXParser();
standardReader = saxParser.getXMLReader();
standardContentHandler = mockContentHandler();
standardReader.setContentHandler(standardContentHandler);
}

View File

@@ -20,6 +20,8 @@ import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -62,13 +64,15 @@ class DomContentHandlerTests {
@BeforeEach
@SuppressWarnings("deprecation") // on JDK 9
void setUp() throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
result = documentBuilder.newDocument();
xmlReader = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true);
SAXParser saxParser = saxParserFactory.newSAXParser();
xmlReader = saxParser.getXMLReader();
}