Skip to content

Commit 94ab872

Browse files
Support LoadBalancer child context creation during AOT processing (#1135)
1 parent 6e610bf commit 94ab872

File tree

8 files changed

+402
-46
lines changed

8 files changed

+402
-46
lines changed

spring-cloud-context/src/main/java/org/springframework/cloud/context/named/NamedContextFactory.java

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.Set;
2525
import java.util.concurrent.ConcurrentHashMap;
2626

27+
import org.springframework.aot.AotDetector;
2728
import org.springframework.beans.BeansException;
2829
import org.springframework.beans.factory.BeanFactoryUtils;
2930
import org.springframework.beans.factory.DisposableBean;
@@ -35,8 +36,11 @@
3536
import org.springframework.context.ApplicationContextAware;
3637
import org.springframework.context.ConfigurableApplicationContext;
3738
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
39+
import org.springframework.context.annotation.AnnotationConfigRegistry;
40+
import org.springframework.context.support.GenericApplicationContext;
3841
import org.springframework.core.ResolvableType;
3942
import org.springframework.core.env.MapPropertySource;
43+
import org.springframework.util.Assert;
4044

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

5660
private final String propertySourceName;
5761

5862
private final String propertyName;
5963

60-
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
64+
private final Map<String, GenericApplicationContext> contexts = new ConcurrentHashMap<>();
6165

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

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

9397
@Override
9498
public void destroy() {
95-
Collection<AnnotationConfigApplicationContext> values = this.contexts.values();
96-
for (AnnotationConfigApplicationContext context : values) {
99+
Collection<GenericApplicationContext> values = this.contexts.values();
100+
for (GenericApplicationContext context : values) {
97101
// This can fail, but it never throws an exception (you see stack traces
98102
// logged as WARN).
99103
context.close();
100104
}
101105
this.contexts.clear();
102106
}
103107

104-
protected AnnotationConfigApplicationContext getContext(String name) {
108+
protected GenericApplicationContext getContext(String name) {
105109
if (!this.contexts.containsKey(name)) {
106110
synchronized (this.contexts) {
107111
if (!this.contexts.containsKey(name)) {
@@ -112,8 +116,39 @@ protected AnnotationConfigApplicationContext getContext(String name) {
112116
return this.contexts.get(name);
113117
}
114118

115-
protected AnnotationConfigApplicationContext createContext(String name) {
116-
AnnotationConfigApplicationContext context;
119+
public void addContext(String contextId, GenericApplicationContext context) {
120+
Assert.notNull(contextId, "contextId cannot be null.");
121+
Assert.notNull(context, "context cannot be null.");
122+
contexts.put(contextId, context);
123+
}
124+
125+
public GenericApplicationContext createContext(String name) {
126+
GenericApplicationContext context = buildContext(name);
127+
registerBeans(name, context);
128+
context.refresh();
129+
return context;
130+
}
131+
132+
public void registerBeans(String name, GenericApplicationContext context) {
133+
Assert.isInstanceOf(AnnotationConfigRegistry.class, context);
134+
AnnotationConfigRegistry registry = (AnnotationConfigRegistry) context;
135+
if (this.configurations.containsKey(name)) {
136+
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
137+
registry.register(configuration);
138+
}
139+
}
140+
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
141+
if (entry.getKey().startsWith("default.")) {
142+
for (Class<?> configuration : entry.getValue().getConfiguration()) {
143+
registry.register(configuration);
144+
}
145+
}
146+
}
147+
registry.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);
148+
}
149+
150+
public GenericApplicationContext buildContext(String name) {
151+
GenericApplicationContext context;
117152
if (this.parent != null) {
118153
// jdk11 issue
119154
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
@@ -126,33 +161,21 @@ protected AnnotationConfigApplicationContext createContext(String name) {
126161
else {
127162
beanFactory.setBeanClassLoader(parent.getClassLoader());
128163
}
129-
context = new AnnotationConfigApplicationContext(beanFactory);
130-
context.setClassLoader(this.parent.getClassLoader());
164+
context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext(beanFactory)
165+
: new AnnotationConfigApplicationContext(beanFactory);
166+
context.setClassLoader(parent.getClassLoader());
131167
}
132168
else {
133-
context = new AnnotationConfigApplicationContext();
134-
}
135-
if (this.configurations.containsKey(name)) {
136-
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
137-
context.register(configuration);
138-
}
169+
context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext()
170+
: new AnnotationConfigApplicationContext();
139171
}
140-
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
141-
if (entry.getKey().startsWith("default.")) {
142-
for (Class<?> configuration : entry.getValue().getConfiguration()) {
143-
context.register(configuration);
144-
}
145-
}
146-
}
147-
context.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);
148-
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName,
149-
Collections.<String, Object>singletonMap(this.propertyName, name)));
172+
context.getEnvironment().getPropertySources().addFirst(
173+
new MapPropertySource(this.propertySourceName, Collections.singletonMap(this.propertyName, name)));
150174
if (this.parent != null) {
151175
// Uses Environment from parent as well as beans
152176
context.setParent(this.parent);
153177
}
154178
context.setDisplayName(generateDisplayName(name));
155-
context.refresh();
156179
return context;
157180
}
158181

@@ -161,7 +184,7 @@ protected String generateDisplayName(String name) {
161184
}
162185

163186
public <T> T getInstance(String name, Class<T> type) {
164-
AnnotationConfigApplicationContext context = getContext(name);
187+
GenericApplicationContext context = getContext(name);
165188
try {
166189
return context.getBean(type);
167190
}
@@ -176,7 +199,7 @@ public <T> ObjectProvider<T> getLazyProvider(String name, Class<T> type) {
176199
}
177200

178201
public <T> ObjectProvider<T> getProvider(String name, Class<T> type) {
179-
AnnotationConfigApplicationContext context = getContext(name);
202+
GenericApplicationContext context = getContext(name);
180203
return context.getBeanProvider(type);
181204
}
182205

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

188211
@SuppressWarnings("unchecked")
189212
public <T> T getInstance(String name, ResolvableType type) {
190-
AnnotationConfigApplicationContext context = getContext(name);
213+
GenericApplicationContext context = getContext(name);
191214
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type);
192215
if (beanNames.length > 0) {
193216
for (String beanName : beanNames) {
@@ -200,11 +223,15 @@ public <T> T getInstance(String name, ResolvableType type) {
200223
}
201224

202225
public <T> Map<String, T> getInstances(String name, Class<T> type) {
203-
AnnotationConfigApplicationContext context = getContext(name);
226+
GenericApplicationContext context = getContext(name);
204227

205228
return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);
206229
}
207230

231+
public Map<String, C> getConfigurations() {
232+
return configurations;
233+
}
234+
208235
/**
209236
* Specification with name and configuration.
210237
*/

spring-cloud-context/src/test/java/org/springframework/cloud/context/named/NamedContextFactoryTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
/**
3939
* @author Spencer Gibb
4040
* @author Tommy Karlsson
41+
* @author Olga Maciaszek-Sharma
4142
*/
4243
public class NamedContextFactoryTests {
4344

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

8889
// get the contexts before destroy() to verify these are the old ones
89-
AnnotationConfigApplicationContext fooContext = factory.getContext("foo");
90-
AnnotationConfigApplicationContext barContext = factory.getContext("bar");
90+
GenericApplicationContext fooContext = factory.getContext("foo");
91+
GenericApplicationContext barContext = factory.getContext("bar");
9192

9293
then(fooContext.getClassLoader()).as("foo context classloader does not match parent")
9394
.isSameAs(parent.getClassLoader());

spring-cloud-loadbalancer/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@
128128
<artifactId>reactor-test</artifactId>
129129
<scope>test</scope>
130130
</dependency>
131+
<dependency>
132+
<groupId>org.springframework</groupId>
133+
<artifactId>spring-core-test</artifactId>
134+
<scope>test</scope>
135+
</dependency>
131136
<dependency>
132137
<groupId>org.awaitility</groupId>
133138
<artifactId>awaitility</artifactId>

spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfigurationRegistrar.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionR
7272
}
7373
registerClientConfiguration(registry, name, attrs.get("defaultConfiguration"));
7474
}
75-
Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName(), true);
75+
Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName());
7676
String name = getClientName(client);
7777
if (name != null) {
7878
registerClientConfiguration(registry, name, client.get("configuration"));

0 commit comments

Comments
 (0)