Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/src/main/asciidoc/_configprops.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
|spring.cloud.discovery.client.health-indicator.include-description | `+++false+++` |
|spring.cloud.discovery.client.health-indicator.use-services-query | `+++true+++` | Whether or not the indicator should use {@link DiscoveryClient#getServices} to check its health. When set to {@code false} the indicator instead uses the lighter {@link DiscoveryClient#probe()}. This can be helpful in large deployments where the number of services returned makes the operation unnecessarily heavy.
|spring.cloud.discovery.client.simple.instances | |
|spring.cloud.discovery.client.simple.local.host | |
|spring.cloud.discovery.client.simple.local.instance-id | |
|spring.cloud.discovery.client.simple.local.metadata | |
|spring.cloud.discovery.client.simple.local.port | `+++0+++` |
|spring.cloud.discovery.client.simple.local.service-id | |
|spring.cloud.discovery.client.simple.local.uri | |
|spring.cloud.discovery.client.simple.order | |
|spring.cloud.discovery.enabled | `+++true+++` | Enables discovery client health indicators.
|spring.cloud.features.enabled | `+++true+++` | Enables the features endpoint.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.aot.AotDetector;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.DisposableBean;
Expand All @@ -35,8 +36,11 @@
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.AnnotationConfigRegistry;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.MapPropertySource;
import org.springframework.util.Assert;

/**
* Creates a set of child contexts that allows a set of Specifications to define the beans
Expand All @@ -48,16 +52,16 @@
* @author Spencer Gibb
* @author Dave Syer
* @author Tommy Karlsson
* @author Olga Maciaszek-Sharma
*/
// TODO: add javadoc
public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
implements DisposableBean, ApplicationContextAware {

private final String propertySourceName;

private final String propertyName;

private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
private final Map<String, GenericApplicationContext> contexts = new ConcurrentHashMap<>();

private Map<String, C> configurations = new ConcurrentHashMap<>();

Expand Down Expand Up @@ -92,16 +96,16 @@ public Set<String> getContextNames() {

@Override
public void destroy() {
Collection<AnnotationConfigApplicationContext> values = this.contexts.values();
for (AnnotationConfigApplicationContext context : values) {
Collection<GenericApplicationContext> values = this.contexts.values();
for (GenericApplicationContext context : values) {
// This can fail, but it never throws an exception (you see stack traces
// logged as WARN).
context.close();
}
this.contexts.clear();
}

protected AnnotationConfigApplicationContext getContext(String name) {
protected GenericApplicationContext getContext(String name) {
if (!this.contexts.containsKey(name)) {
synchronized (this.contexts) {
if (!this.contexts.containsKey(name)) {
Expand All @@ -112,8 +116,39 @@ protected AnnotationConfigApplicationContext getContext(String name) {
return this.contexts.get(name);
}

protected AnnotationConfigApplicationContext createContext(String name) {
AnnotationConfigApplicationContext context;
public void addContext(String contextId, GenericApplicationContext context) {
Assert.notNull(contextId, "contextId cannot be null.");
Assert.notNull(context, "context cannot be null.");
contexts.put(contextId, context);
}

public GenericApplicationContext createContext(String name) {
GenericApplicationContext context = buildContext(name);
registerBeans(name, context);
context.refresh();
return context;
}

public void registerBeans(String name, GenericApplicationContext context) {
Assert.isInstanceOf(AnnotationConfigRegistry.class, context);
AnnotationConfigRegistry registry = (AnnotationConfigRegistry) context;
if (this.configurations.containsKey(name)) {
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
registry.register(configuration);
}
}
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
if (entry.getKey().startsWith("default.")) {
for (Class<?> configuration : entry.getValue().getConfiguration()) {
registry.register(configuration);
}
}
}
registry.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);
}

public GenericApplicationContext buildContext(String name) {
GenericApplicationContext context;
if (this.parent != null) {
// jdk11 issue
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
Expand All @@ -126,33 +161,21 @@ protected AnnotationConfigApplicationContext createContext(String name) {
else {
beanFactory.setBeanClassLoader(parent.getClassLoader());
}
context = new AnnotationConfigApplicationContext(beanFactory);
context.setClassLoader(this.parent.getClassLoader());
context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext(beanFactory)
: new AnnotationConfigApplicationContext(beanFactory);
context.setClassLoader(parent.getClassLoader());
}
else {
context = new AnnotationConfigApplicationContext();
}
if (this.configurations.containsKey(name)) {
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
context.register(configuration);
}
context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext()
: new AnnotationConfigApplicationContext();
}
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
if (entry.getKey().startsWith("default.")) {
for (Class<?> configuration : entry.getValue().getConfiguration()) {
context.register(configuration);
}
}
}
context.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName,
Collections.<String, Object>singletonMap(this.propertyName, name)));
context.getEnvironment().getPropertySources().addFirst(
new MapPropertySource(this.propertySourceName, Collections.singletonMap(this.propertyName, name)));
if (this.parent != null) {
// Uses Environment from parent as well as beans
context.setParent(this.parent);
}
context.setDisplayName(generateDisplayName(name));
context.refresh();
return context;
}

Expand All @@ -161,7 +184,7 @@ protected String generateDisplayName(String name) {
}

public <T> T getInstance(String name, Class<T> type) {
AnnotationConfigApplicationContext context = getContext(name);
GenericApplicationContext context = getContext(name);
try {
return context.getBean(type);
}
Expand All @@ -176,7 +199,7 @@ public <T> ObjectProvider<T> getLazyProvider(String name, Class<T> type) {
}

public <T> ObjectProvider<T> getProvider(String name, Class<T> type) {
AnnotationConfigApplicationContext context = getContext(name);
GenericApplicationContext context = getContext(name);
return context.getBeanProvider(type);
}

Expand All @@ -187,7 +210,7 @@ public <T> T getInstance(String name, Class<?> clazz, Class<?>... generics) {

@SuppressWarnings("unchecked")
public <T> T getInstance(String name, ResolvableType type) {
AnnotationConfigApplicationContext context = getContext(name);
GenericApplicationContext context = getContext(name);
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type);
if (beanNames.length > 0) {
for (String beanName : beanNames) {
Expand All @@ -200,11 +223,15 @@ public <T> T getInstance(String name, ResolvableType type) {
}

public <T> Map<String, T> getInstances(String name, Class<T> type) {
AnnotationConfigApplicationContext context = getContext(name);
GenericApplicationContext context = getContext(name);

return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);
}

public Map<String, C> getConfigurations() {
return configurations;
}

/**
* Specification with name and configuration.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
/**
* @author Spencer Gibb
* @author Tommy Karlsson
* @author Olga Maciaszek-Sharma
*/
public class NamedContextFactoryTests {

Expand Down Expand Up @@ -86,8 +87,8 @@ private void testChildContexts(GenericApplicationContext parent) {
then(barBazes.size()).as("barBazes size was wrong").isEqualTo(2);

// get the contexts before destroy() to verify these are the old ones
AnnotationConfigApplicationContext fooContext = factory.getContext("foo");
AnnotationConfigApplicationContext barContext = factory.getContext("bar");
GenericApplicationContext fooContext = factory.getContext("foo");
GenericApplicationContext barContext = factory.getContext("bar");

then(fooContext.getClassLoader()).as("foo context classloader does not match parent")
.isSameAs(parent.getClassLoader());
Expand Down
5 changes: 5 additions & 0 deletions spring-cloud-loadbalancer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ private static void registerClientConfiguration(BeanDefinitionRegistry registry,

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
Map<String, Object> attrs = metadata.getAnnotationAttributes(LoadBalancerClients.class.getName(), true);
Map<String, Object> attrs = metadata.getAnnotationAttributes(LoadBalancerClients.class.getName());
if (attrs != null && attrs.containsKey("value")) {
AnnotationAttributes[] clients = (AnnotationAttributes[]) attrs.get("value");
for (AnnotationAttributes client : clients) {
Expand All @@ -72,7 +72,7 @@ public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionR
}
registerClientConfiguration(registry, name, attrs.get("defaultConfiguration"));
}
Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName(), true);
Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName());
String name = getClientName(client);
if (name != null) {
registerClientConfiguration(registry, name, client.get("configuration"));
Expand Down
Loading