From 8d5cf79675598b66131cdfd2c9a8e27a33b726bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Wed, 24 Jun 2020 17:27:02 +0200 Subject: [PATCH 1/2] Disable XML reader when spring.xml.ignore is true This commit allows to set the XmlBeanDefinitionReader field from BeanDefinitionLoader to null in a way that allows the GraalVM native compiler to remove it from the native image when the spring.xml.ignore flag introduced by spring-projects/spring-framework#25151 is set to true. The purpose of this change is to allow smaller footprint on native images without requiring to use GraalVM native substitutions which are unmaintainable by nature and also to increase the consistency between JVM and native images. In order to effective, this optimization requires BeanDefinitionLoader class to be initialized at build time. See gh-22093 --- .../boot/BeanDefinitionLoader.java | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java index 9e29d1912b..bd8b850f61 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java @@ -32,6 +32,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; +import org.springframework.core.SpringProperties; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -53,17 +54,27 @@ import org.springframework.util.StringUtils; * * @author Phillip Webb * @author Vladislav Kisel + * @author Sebastien Deleuze * @see #setBeanNameGenerator(BeanNameGenerator) */ class BeanDefinitionLoader { + /** + * Boolean flag controlled by a {@code spring.xml.ignore} system property that + * instructs Spring to ignore XML, i.e. to not initialize the XML-related + * infrastructure. + *

+ * By default XML support is enabled. + */ + private static final boolean IS_XML_ENABLED = !SpringProperties.getFlag("spring.xml.ignore"); + private final Object[] sources; private final AnnotatedBeanDefinitionReader annotatedReader; private final XmlBeanDefinitionReader xmlReader; - private BeanDefinitionReader groovyReader; + private final BeanDefinitionReader groovyReader; private final ClassPathBeanDefinitionScanner scanner; @@ -80,10 +91,8 @@ class BeanDefinitionLoader { Assert.notEmpty(sources, "Sources must not be empty"); this.sources = sources; this.annotatedReader = new AnnotatedBeanDefinitionReader(registry); - this.xmlReader = new XmlBeanDefinitionReader(registry); - if (isGroovyPresent()) { - this.groovyReader = new GroovyBeanDefinitionReader(registry); - } + this.xmlReader = (IS_XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null); + this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null); this.scanner = new ClassPathBeanDefinitionScanner(registry); this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); } @@ -94,8 +103,10 @@ class BeanDefinitionLoader { */ void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { this.annotatedReader.setBeanNameGenerator(beanNameGenerator); - this.xmlReader.setBeanNameGenerator(beanNameGenerator); this.scanner.setBeanNameGenerator(beanNameGenerator); + if (IS_XML_ENABLED) { + this.xmlReader.setBeanNameGenerator(beanNameGenerator); + } } /** @@ -104,8 +115,10 @@ class BeanDefinitionLoader { */ void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; - this.xmlReader.setResourceLoader(resourceLoader); this.scanner.setResourceLoader(resourceLoader); + if (IS_XML_ENABLED) { + this.xmlReader.setResourceLoader(resourceLoader); + } } /** @@ -114,8 +127,10 @@ class BeanDefinitionLoader { */ void setEnvironment(ConfigurableEnvironment environment) { this.annotatedReader.setEnvironment(environment); - this.xmlReader.setEnvironment(environment); this.scanner.setEnvironment(environment); + if (IS_XML_ENABLED) { + this.xmlReader.setEnvironment(environment); + } } /** @@ -167,6 +182,9 @@ class BeanDefinitionLoader { this.groovyReader.loadBeanDefinitions(source); } else { + if (!IS_XML_ENABLED) { + throw new BeanDefinitionStoreException("Cannot load resources when XML support is disabled"); + } this.xmlReader.loadBeanDefinitions(source); } } From 308e33700905883718f8029a557cf621c1c85b0a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 25 Jun 2020 10:56:39 +0100 Subject: [PATCH 2/2] Polish "Disable XML reader when spring.xml.ignore is true" See gh-22093 --- .../boot/BeanDefinitionLoader.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java index bd8b850f61..6719541f47 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java @@ -26,6 +26,7 @@ import groovy.lang.Closure; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader; +import org.springframework.beans.factory.support.AbstractBeanDefinitionReader; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; @@ -59,20 +60,14 @@ import org.springframework.util.StringUtils; */ class BeanDefinitionLoader { - /** - * Boolean flag controlled by a {@code spring.xml.ignore} system property that - * instructs Spring to ignore XML, i.e. to not initialize the XML-related - * infrastructure. - *

- * By default XML support is enabled. - */ - private static final boolean IS_XML_ENABLED = !SpringProperties.getFlag("spring.xml.ignore"); + // Static final field to facilitate code removal by Graal + private static final boolean XML_ENABLED = !SpringProperties.getFlag("spring.xml.ignore"); private final Object[] sources; private final AnnotatedBeanDefinitionReader annotatedReader; - private final XmlBeanDefinitionReader xmlReader; + private final AbstractBeanDefinitionReader xmlReader; private final BeanDefinitionReader groovyReader; @@ -91,7 +86,7 @@ class BeanDefinitionLoader { Assert.notEmpty(sources, "Sources must not be empty"); this.sources = sources; this.annotatedReader = new AnnotatedBeanDefinitionReader(registry); - this.xmlReader = (IS_XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null); + this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null); this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null); this.scanner = new ClassPathBeanDefinitionScanner(registry); this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); @@ -104,7 +99,7 @@ class BeanDefinitionLoader { void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { this.annotatedReader.setBeanNameGenerator(beanNameGenerator); this.scanner.setBeanNameGenerator(beanNameGenerator); - if (IS_XML_ENABLED) { + if (this.xmlReader != null) { this.xmlReader.setBeanNameGenerator(beanNameGenerator); } } @@ -116,7 +111,7 @@ class BeanDefinitionLoader { void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; this.scanner.setResourceLoader(resourceLoader); - if (IS_XML_ENABLED) { + if (this.xmlReader != null) { this.xmlReader.setResourceLoader(resourceLoader); } } @@ -128,7 +123,7 @@ class BeanDefinitionLoader { void setEnvironment(ConfigurableEnvironment environment) { this.annotatedReader.setEnvironment(environment); this.scanner.setEnvironment(environment); - if (IS_XML_ENABLED) { + if (this.xmlReader != null) { this.xmlReader.setEnvironment(environment); } } @@ -182,8 +177,8 @@ class BeanDefinitionLoader { this.groovyReader.loadBeanDefinitions(source); } else { - if (!IS_XML_ENABLED) { - throw new BeanDefinitionStoreException("Cannot load resources when XML support is disabled"); + if (this.xmlReader == null) { + throw new BeanDefinitionStoreException("Cannot load XML bean definitions when XML support is disabled"); } this.xmlReader.loadBeanDefinitions(source); }