diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java index e376a3a9..372a89cf 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java @@ -158,14 +158,6 @@ public class BootstrapApplicationListener } bootstrapProperties.addLast(source); } - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - // Use names and ensure unique to protect against duplicates - List names = new ArrayList<>(SpringFactoriesLoader - .loadFactoryNames(BootstrapConfiguration.class, classLoader)); - for (String name : StringUtils.commaDelimitedListToStringArray( - environment.getProperty("spring.cloud.bootstrap.sources", ""))) { - names.add(name); - } // TODO: is it possible or sensible to share a ResourceLoader? SpringApplicationBuilder builder = new SpringApplicationBuilder() .profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF) @@ -192,19 +184,7 @@ public class BootstrapApplicationListener builderApplication .setListeners(filterListeners(builderApplication.getListeners())); } - List> sources = new ArrayList<>(); - for (String name : names) { - Class cls = ClassUtils.resolveClassName(name, null); - try { - cls.getDeclaredAnnotations(); - } - catch (Exception e) { - continue; - } - sources.add(cls); - } - AnnotationAwareOrderComparator.sort(sources); - builder.sources(sources.toArray(new Class[sources.size()])); + builder.sources(BootstrapImportSelectorConfiguration.class); final ConfigurableApplicationContext context = builder.run(); // gh-214 using spring.application.name=bootstrap to set the context id via // `ContextIdApplicationContextInitializer` prevents apps from getting the actual diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapImportSelector.java b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapImportSelector.java new file mode 100644 index 00000000..6215cd11 --- /dev/null +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapImportSelector.java @@ -0,0 +1,78 @@ +/* + * Copyright 2013-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.bootstrap; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.context.EnvironmentAware; +import org.springframework.context.annotation.DeferredImportSelector; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.env.Environment; +import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +/** + * This class uses {@link SpringFactoriesLoader} to load {@link BootstrapConfiguration} + * entries from {@code spring.factories}. The classes are then loaded so they can + * be sorted using {@link AnnotationAwareOrderComparator#sort(List)}. + * This class is a {@link DeferredImportSelector} so {@code @Conditional} annotations + * on imported classes are supported. + */ +public class BootstrapImportSelector implements EnvironmentAware, DeferredImportSelector { + + private Environment environment; + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Override + public String[] selectImports(AnnotationMetadata metadata) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + // Use names and ensure unique to protect against duplicates + List names = new ArrayList<>(SpringFactoriesLoader + .loadFactoryNames(BootstrapConfiguration.class, classLoader)); + names.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray( + environment.getProperty("spring.cloud.bootstrap.sources", "")))); + + List> sources = new ArrayList<>(); + for (String name : names) { + Class cls = ClassUtils.resolveClassName(name, null); + try { + cls.getDeclaredAnnotations(); + } + catch (Exception e) { + continue; + } + sources.add(cls); + } + AnnotationAwareOrderComparator.sort(sources); + + List classNames = sources.stream() + .map(Class::getName) + .collect(Collectors.toList()); + + + return classNames.toArray(new String[0]); + } +} diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapImportSelectorConfiguration.java b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapImportSelectorConfiguration.java new file mode 100644 index 00000000..318cdde1 --- /dev/null +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapImportSelectorConfiguration.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.bootstrap; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(BootstrapImportSelector.class) +public class BootstrapImportSelectorConfiguration { +}