Skip to content

Commit 4092427

Browse files
artembilangaryrussell
authored andcommitted
GH-3253: Scan BF hierarchy for BeanDefinition
Fixes #3253 The `IntegrationFlowBeanPostProcessor` uses a `containsBean()` and then `getBeanDefinition()` to be sure that we don't override already existing bean even if it is created in the parent(s) context. The problem that `containsBean()` check the hierarchy, but `getBeanDefinition()` doesn't. So, we fail with `NoSuchBeanDefinitionException` if bean exists in the parent ctx * Introduce an utility `IntegrationContextUtils.getBeanDefinition()` to scan `BeanFactory` recursively for `BeanDefinition` for the requested `name` * Use this tool in the `IntegrationFlowBeanPostProcessor` logic **Cherry-pick to 5.2.x & 5.1.x**
1 parent e73e08b commit 4092427

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,9 @@
1919
import java.util.Properties;
2020

2121
import org.springframework.beans.factory.BeanFactory;
22+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
23+
import org.springframework.beans.factory.config.BeanDefinition;
24+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2225
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
2326
import org.springframework.beans.factory.support.RootBeanDefinition;
2427
import org.springframework.expression.spel.support.SimpleEvaluationContext;
@@ -212,4 +215,26 @@ public static Properties getIntegrationProperties(BeanFactory beanFactory) {
212215
return properties;
213216
}
214217

218+
/**
219+
* Return a {@link BeanDefinition} with the given name,
220+
* obtained from the given {@link BeanFactory} or one of its parents.
221+
* @param name the bean name to return
222+
* @param beanFactory the {@link ConfigurableListableBeanFactory} to travers.
223+
* @return the {@link BeanDefinition} for a given name
224+
* @throws NoSuchBeanDefinitionException if a {@link BeanDefinition} is not found
225+
* @since 5.1.10
226+
*/
227+
public static BeanDefinition getBeanDefinition(String name, ConfigurableListableBeanFactory beanFactory) {
228+
try {
229+
return beanFactory.getBeanDefinition(name);
230+
}
231+
catch (NoSuchBeanDefinitionException ex) {
232+
BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
233+
if (parentBeanFactory instanceof ConfigurableListableBeanFactory) {
234+
return getBeanDefinition(name, (ConfigurableListableBeanFactory) parentBeanFactory);
235+
}
236+
throw ex;
237+
}
238+
}
239+
215240
}

spring-integration-core/src/main/java/org/springframework/integration/dsl/context/IntegrationFlowBeanPostProcessor.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2019 the original author or authors.
2+
* Copyright 2016-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -57,6 +57,7 @@
5757
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
5858
import org.springframework.integration.config.IntegrationConfigUtils;
5959
import org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean;
60+
import org.springframework.integration.context.IntegrationContextUtils;
6061
import org.springframework.integration.core.MessageSource;
6162
import org.springframework.integration.dsl.ComponentsRegistration;
6263
import org.springframework.integration.dsl.ConsumerEndpointSpec;
@@ -138,7 +139,8 @@ public void afterSingletonsInstantiated() {
138139
}
139140
}
140141

141-
private Object processStandardIntegrationFlow(StandardIntegrationFlow flow, String flowBeanName) { // NOSONAR complexity
142+
private Object processStandardIntegrationFlow(StandardIntegrationFlow flow, String flowBeanName) { // NOSONAR
143+
// complexity
142144
String flowNamePrefix = flowBeanName + ".";
143145
if (this.flowContext == null) {
144146
this.flowContext = this.beanFactory.getBean(IntegrationFlowContext.class);
@@ -283,7 +285,9 @@ else if (component instanceof AnnotationGatewayProxyFactoryBean) {
283285
String beanNameToUse = entry.getValue();
284286
if (StringUtils.hasText(beanNameToUse) &&
285287
ConfigurableBeanFactory.SCOPE_PROTOTYPE.equals(
286-
this.beanFactory.getBeanDefinition(beanNameToUse).getScope())) {
288+
IntegrationContextUtils.getBeanDefinition(beanNameToUse, this.beanFactory)
289+
.getScope())) {
290+
287291
this.beanFactory.initializeBean(componentToUse, beanNameToUse);
288292
}
289293
targetIntegrationComponents.put(component, beanNameToUse);
@@ -393,7 +397,8 @@ private boolean noBeanPresentForComponent(Object instance, String parentBeanName
393397
String beanName = ((NamedComponent) instance).getBeanName();
394398
if (beanName != null) {
395399
if (this.beanFactory.containsBean(beanName)) {
396-
BeanDefinition existingBeanDefinition = this.beanFactory.getBeanDefinition(beanName);
400+
BeanDefinition existingBeanDefinition =
401+
IntegrationContextUtils.getBeanDefinition(beanName, this.beanFactory);
397402
if (!ConfigurableBeanFactory.SCOPE_PROTOTYPE.equals(existingBeanDefinition.getScope())
398403
&& !instance.equals(this.beanFactory.getBean(beanName))) {
399404

@@ -429,8 +434,8 @@ private void registerComponent(Object component, String beanName, String parentN
429434

430435
AbstractBeanDefinition beanDefinition =
431436
BeanDefinitionBuilder.genericBeanDefinition((Class<Object>) component.getClass(), () -> component)
432-
.applyCustomizers(customizers)
433-
.getRawBeanDefinition();
437+
.applyCustomizers(customizers)
438+
.getRawBeanDefinition();
434439

435440
if (parentName != null && this.beanFactory.containsBeanDefinition(parentName)) {
436441
AbstractBeanDefinition parentBeanDefinition =

0 commit comments

Comments
 (0)