From 77edb27a073ce32d1bf148520393e218b8395ed4 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 20 Apr 2022 16:23:38 -0700 Subject: [PATCH] Fix package tangle caused by ApplicationContextFactory Fix package tangle by changing `ApplicationContextFactory.DEFAULT` to use `spring.factories` to discover implementations rather than needing direct access to our own `ApplicationContext` classes. Closes gh-30272 --- .../boot/ApplicationContextFactory.java | 19 +++++++++---------- ...igReactiveWebServerApplicationContext.java | 19 ++++++++++++++++++- ...figServletWebServerApplicationContext.java | 19 ++++++++++++++++++- .../main/resources/META-INF/spring.factories | 5 +++++ 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ApplicationContextFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ApplicationContextFactory.java index d17ee20d31d6..9f9d08e71aae 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ApplicationContextFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ApplicationContextFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,9 @@ import java.util.function.Supplier; import org.springframework.beans.BeanUtils; -import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; -import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.core.io.support.SpringFactoriesLoader; /** * Strategy interface for creating the {@link ConfigurableApplicationContext} used by a @@ -43,14 +42,14 @@ public interface ApplicationContextFactory { */ ApplicationContextFactory DEFAULT = (webApplicationType) -> { try { - switch (webApplicationType) { - case SERVLET: - return new AnnotationConfigServletWebServerApplicationContext(); - case REACTIVE: - return new AnnotationConfigReactiveWebServerApplicationContext(); - default: - return new AnnotationConfigApplicationContext(); + for (ApplicationContextFactory candidate : SpringFactoriesLoader + .loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader())) { + ConfigurableApplicationContext context = candidate.create(webApplicationType); + if (context != null) { + return context; + } } + return new AnnotationConfigApplicationContext(); } catch (Exception ex) { throw new IllegalStateException("Unable create a default ApplicationContext instance, " diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContext.java index 8a2f68865f0a..9c9e3b6974fc 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,9 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.ApplicationContextFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigRegistry; @@ -209,4 +212,18 @@ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactor } } + /** + * {@link ApplicationContextFactory} registered in {@code spring.factories} to support + * {@link AnnotationConfigReactiveWebServerApplicationContext}. + */ + static class Factory implements ApplicationContextFactory { + + @Override + public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.REACTIVE) ? null + : new AnnotationConfigReactiveWebServerApplicationContext(); + } + + } + } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContext.java index 0b1775b9a6bb..2513b0cf3f4a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,9 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.ApplicationContextFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; import org.springframework.context.annotation.AnnotationConfigRegistry; import org.springframework.context.annotation.AnnotationConfigUtils; @@ -206,4 +209,18 @@ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactor } } + /** + * {@link ApplicationContextFactory} registered in {@code spring.factories} to support + * {@link AnnotationConfigServletWebServerApplicationContext}. + */ + static class Factory implements ApplicationContextFactory { + + @Override + public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { + return (webApplicationType != WebApplicationType.SERVLET) ? null + : new AnnotationConfigServletWebServerApplicationContext(); + } + + } + } diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories index dad1a4313529..9247d9393968 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories @@ -19,6 +19,11 @@ org.springframework.boot.context.config.ConfigDataLoader=\ org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\ org.springframework.boot.context.config.StandardConfigDataLoader +# Application Context Factories +org.springframework.boot.ApplicationContextFactory=\ +org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\ +org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory + # Run Listeners org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener