Skip to content

Commit 305e39a

Browse files
committed
Force user-defined member beans instantiation.
1 parent 1e7d04c commit 305e39a

11 files changed

+60
-24
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/AbstractInterfaceClientsFactoryBean.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.springframework.beans.factory.InitializingBean;
2222
import org.springframework.context.ApplicationContext;
2323
import org.springframework.context.ApplicationContextAware;
24+
import org.springframework.context.ConfigurableApplicationContext;
2425
import org.springframework.util.Assert;
2526

2627
/**
@@ -35,7 +36,7 @@ public abstract class AbstractInterfaceClientsFactoryBean
3536

3637
protected String clientId;
3738

38-
protected ApplicationContext applicationContext;
39+
protected ConfigurableApplicationContext applicationContext;
3940

4041
public AbstractInterfaceClientsFactoryBean() {
4142
}
@@ -58,7 +59,9 @@ public Class<?> getObjectType() {
5859

5960
@Override
6061
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
61-
this.applicationContext = applicationContext;
62+
Assert.isInstanceOf(ConfigurableApplicationContext.class, applicationContext,
63+
"ApplicationContext must be an instance of " + ConfigurableApplicationContext.class.getSimpleName());
64+
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
6265

6366
}
6467

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/AbstractInterfaceClientsImportRegistrar.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ public abstract class AbstractInterfaceClientsImportRegistrar
5858

5959
// TODO: work on IntelliJ plugin /other plugins/ to show that the client beans are
6060
// autoconfigured
61-
private static final Log logger = LogFactory.getLog(AbstractInterfaceClientsImportRegistrar.class);
6261

6362
private static final String INTERFACE_CLIENT_SUFFIX = "InterfaceClient";
6463

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/InterfaceClientsAdapter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.autoconfigure.interfaceclients;
1818

1919
import org.springframework.beans.factory.ListableBeanFactory;
20+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2021
import org.springframework.core.Ordered;
2122

2223
/**
@@ -27,6 +28,6 @@ public interface InterfaceClientsAdapter extends Ordered {
2728

2829
String DEFAULT_QUALIFIER = "interfaceClients";
2930

30-
<T> T createClient(ListableBeanFactory beanFactory, String clientId, Class<T> type);
31+
<T> T createClient(ConfigurableListableBeanFactory beanFactory, String clientId, Class<T> type);
3132

3233
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/http/AbstractHttpInterfaceClientsFactoryBean.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public Object getObject() throws Exception {
3737
}
3838

3939
private HttpServiceProxyFactory proxyFactory() {
40-
HttpServiceProxyFactory userProvidedProxyFactory = QualifiedBeanProvider.qualifiedBean(this.applicationContext,
41-
HttpServiceProxyFactory.class, this.clientId);
40+
HttpServiceProxyFactory userProvidedProxyFactory = QualifiedBeanProvider
41+
.qualifiedBean(this.applicationContext.getBeanFactory(), HttpServiceProxyFactory.class, this.clientId);
4242
if (userProvidedProxyFactory != null) {
4343
return userProvidedProxyFactory;
4444
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/http/HttpExchangeAdapterProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package org.springframework.boot.autoconfigure.interfaceclients.http;
1818

19-
import org.springframework.beans.factory.ListableBeanFactory;
19+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2020
import org.springframework.web.service.invoker.HttpExchangeAdapter;
2121

2222
/**
@@ -26,6 +26,6 @@
2626
public interface HttpExchangeAdapterProvider {
2727

2828
// TODO: try a less specific type for the beanFactory
29-
HttpExchangeAdapter get(ListableBeanFactory beanFactory, String clientId);
29+
HttpExchangeAdapter get(ConfigurableListableBeanFactory beanFactory, String clientId);
3030

3131
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/http/HttpInterfaceClientsAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.apache.commons.logging.LogFactory;
2121

2222
import org.springframework.beans.factory.ListableBeanFactory;
23+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2324
import org.springframework.boot.autoconfigure.interfaceclients.InterfaceClientsAdapter;
2425
import org.springframework.web.service.invoker.HttpExchangeAdapter;
2526
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
@@ -38,13 +39,13 @@ public HttpInterfaceClientsAdapter(HttpExchangeAdapterProvider adapterProvider)
3839
}
3940

4041
@Override
41-
public <T> T createClient(ListableBeanFactory beanFactory, String clientId, Class<T> type) {
42+
public <T> T createClient(ConfigurableListableBeanFactory beanFactory, String clientId, Class<T> type) {
4243
HttpServiceProxyFactory proxyFactory = proxyFactory(beanFactory, clientId);
4344

4445
return proxyFactory.createClient(type);
4546
}
4647

47-
private HttpServiceProxyFactory proxyFactory(ListableBeanFactory beanFactory, String clientId) {
48+
private HttpServiceProxyFactory proxyFactory(ConfigurableListableBeanFactory beanFactory, String clientId) {
4849
HttpServiceProxyFactory userProvidedProxyFactory = QualifiedBeanProvider.qualifiedBean(beanFactory,
4950
HttpServiceProxyFactory.class, clientId);
5051
if (userProvidedProxyFactory != null) {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/http/QualifiedBeanProvider.java

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,21 @@
1616

1717
package org.springframework.boot.autoconfigure.interfaceclients.http;
1818

19+
import java.util.HashMap;
1920
import java.util.Map;
2021

2122
import org.apache.commons.logging.Log;
2223
import org.apache.commons.logging.LogFactory;
2324

24-
import org.springframework.beans.factory.ListableBeanFactory;
25+
import org.springframework.beans.factory.BeanFactoryUtils;
2526
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
26-
27-
import static org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils.qualifiedBeansOfType;
27+
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
28+
import org.springframework.beans.factory.annotation.Qualifier;
29+
import org.springframework.beans.factory.config.BeanDefinition;
30+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
31+
import org.springframework.core.annotation.AnnotationAttributes;
32+
import org.springframework.core.annotation.MergedAnnotation;
33+
import org.springframework.core.type.MethodMetadata;
2834

2935
/**
3036
* @author Olga Maciaszek-Sharma
@@ -33,16 +39,16 @@ final class QualifiedBeanProvider {
3339

3440
private static final Log logger = LogFactory.getLog(QualifiedBeanProvider.class);
3541

36-
static <T> T qualifiedBean(ListableBeanFactory beanFactory, Class<T> type, String clientId) {
37-
Map<String, T> matchingClientBeans = qualifiedBeansOfType(beanFactory, type, clientId);
42+
static <T> T qualifiedBean(ConfigurableListableBeanFactory beanFactory, Class<T> type, String clientId) {
43+
Map<String, T> matchingClientBeans = getQualifiedBeansOfType(beanFactory, type, clientId);
3844
if (matchingClientBeans.size() > 1) {
3945
throw new NoUniqueBeanDefinitionException(type, matchingClientBeans.keySet());
4046
}
4147
if (matchingClientBeans.isEmpty()) {
4248
if (logger.isDebugEnabled()) {
4349
logger.debug("No qualified bean of type " + type + " found for " + clientId);
4450
}
45-
Map<String, T> matchingDefaultBeans = qualifiedBeansOfType(beanFactory, type, clientId);
51+
Map<String, T> matchingDefaultBeans = getQualifiedBeansOfType(beanFactory, type, clientId);
4652
if (matchingDefaultBeans.size() > 1) {
4753
throw new NoUniqueBeanDefinitionException(type, matchingDefaultBeans.keySet());
4854
}
@@ -56,4 +62,28 @@ static <T> T qualifiedBean(ListableBeanFactory beanFactory, Class<T> type, Strin
5662
return matchingClientBeans.values().iterator().next();
5763
}
5864

65+
private static <T> Map<String, T> getQualifiedBeansOfType(ConfigurableListableBeanFactory beanFactory,
66+
Class<T> type, String clientId) {
67+
Map<String, T> beansOfType = BeanFactoryUtils.beansOfTypeIncludingAncestors(beanFactory, type);
68+
Map<String, T> matchingClientBeans = new HashMap<>();
69+
for (String beanName : beansOfType.keySet()) {
70+
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
71+
if (beanDefinition instanceof AnnotatedBeanDefinition definition) {
72+
// TODO: try refactoring this
73+
// TODO: beans defined in a different way
74+
// AnnotationAttributes annotationAttributes = AnnotationAttributes
75+
// .fromMap(definition.getMetadata().getAnnotationAttributes(Qualifier.class.getName()));
76+
MethodMetadata methodMetadata = definition.getFactoryMethodMetadata();
77+
AnnotationAttributes annotationAttributes = methodMetadata != null ? AnnotationAttributes
78+
.fromMap(methodMetadata.getAnnotationAttributes(Qualifier.class.getName())) : null;
79+
if (annotationAttributes != null
80+
&& clientId.equals(annotationAttributes.getString(MergedAnnotation.VALUE))) {
81+
matchingClientBeans.put(beanName, beansOfType.get(beanName));
82+
}
83+
84+
}
85+
}
86+
return matchingClientBeans;
87+
}
88+
5989
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/http/RestClientAdapterProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.springframework.beans.factory.ListableBeanFactory;
2323
import org.springframework.beans.factory.ObjectProvider;
24+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2425
import org.springframework.web.client.RestClient;
2526
import org.springframework.web.client.support.RestClientAdapter;
2627
import org.springframework.web.service.invoker.HttpExchangeAdapter;
@@ -43,7 +44,7 @@ public RestClientAdapterProvider(RestClient.Builder builder,
4344
}
4445

4546
@Override
46-
public HttpExchangeAdapter get(ListableBeanFactory beanFactory, String clientId) {
47+
public HttpExchangeAdapter get(ConfigurableListableBeanFactory beanFactory, String clientId) {
4748
RestClient userProvidedRestClient = QualifiedBeanProvider.qualifiedBean(beanFactory, RestClient.class,
4849
clientId);
4950
if (userProvidedRestClient != null) {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/http/RestClientInterfaceClientsFactoryBean.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@ protected HttpExchangeAdapter exchangeAdapter() {
3838
// it should not be set in properties.
3939
String baseUrl = properties.getProperties(this.clientId).getBaseUrl();
4040

41-
RestClient userProvidedRestClient = QualifiedBeanProvider.qualifiedBean(this.applicationContext,
42-
RestClient.class, this.clientId);
41+
RestClient userProvidedRestClient = QualifiedBeanProvider
42+
.qualifiedBean(this.applicationContext.getBeanFactory(), RestClient.class, this.clientId);
4343
if (userProvidedRestClient != null) {
4444
if (baseUrl != null) {
4545
userProvidedRestClient = userProvidedRestClient.mutate().baseUrl(baseUrl).build();
4646
}
4747
return RestClientAdapter.create(userProvidedRestClient);
4848
}
4949

50-
RestClient.Builder userProvidedRestClientBuilder = QualifiedBeanProvider.qualifiedBean(this.applicationContext,
51-
RestClient.Builder.class, this.clientId);
50+
RestClient.Builder userProvidedRestClientBuilder = QualifiedBeanProvider
51+
.qualifiedBean(this.applicationContext.getBeanFactory(), RestClient.Builder.class, this.clientId);
5252
if (userProvidedRestClientBuilder != null) {
5353

5454
if (baseUrl != null) {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/interfaceclients/http/RestTemplateAdapterProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import org.apache.commons.logging.Log;
2020
import org.apache.commons.logging.LogFactory;
2121

22-
import org.springframework.beans.factory.ListableBeanFactory;
2322
import org.springframework.beans.factory.ObjectProvider;
23+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2424
import org.springframework.boot.web.client.RestTemplateBuilder;
2525
import org.springframework.web.client.RestTemplate;
2626
import org.springframework.web.client.support.RestTemplateAdapter;
@@ -44,7 +44,7 @@ public RestTemplateAdapterProvider(RestTemplateBuilder restTemplateBuilder,
4444
}
4545

4646
@Override
47-
public HttpExchangeAdapter get(ListableBeanFactory beanFactory, String clientId) {
47+
public HttpExchangeAdapter get(ConfigurableListableBeanFactory beanFactory, String clientId) {
4848
RestTemplate userProvidedRestTemplate = QualifiedBeanProvider.qualifiedBean(beanFactory, RestTemplate.class,
4949
clientId);
5050
if (userProvidedRestTemplate != null) {

0 commit comments

Comments
 (0)