INT-4513: Clean IntManageConf from removed beans

JIRA: https://jira.spring.io/browse/INT-4513

The `IntegrationManagementConfigurer` keeps metrics beans in its local
stores.
When we add beans at runtime, they are not removed from those caches
after their removal

* Implement `DestructionAwareBeanPostProcessor` in the `IntegrationManagementConfigurer`
and clean up caches according provided bean type and its name
* Improve `ManualFlowTests` and `FtpTests` to be sure that
`IntegrationManagementConfigurer` caches are cleared after destroying
 `IntegrationFlowRegistration`

**Cherry-pick to 5.0.x**
This commit is contained in:
Artem Bilan
2018-07-27 12:36:39 -04:00
committed by Gary Russell
parent bd0fd50313
commit adbbca13fb
3 changed files with 57 additions and 5 deletions

View File

@@ -27,7 +27,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.integration.core.MessageSource;
@@ -64,8 +64,9 @@ import org.springframework.util.StringUtils;
* @since 4.2
*
*/
public class IntegrationManagementConfigurer implements SmartInitializingSingleton, ApplicationContextAware,
BeanNameAware, BeanPostProcessor {
public class IntegrationManagementConfigurer
implements SmartInitializingSingleton, ApplicationContextAware, BeanNameAware,
DestructionAwareBeanPostProcessor {
private static final Log logger = LogFactory.getLog(IntegrationManagementConfigurer.class);
@@ -246,7 +247,8 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet
this.metricsFactory = new DefaultMetricsFactory();
}
this.sourceConfigurers.putAll(this.applicationContext.getBeansOfType(MessageSourceMetricsConfigurer.class));
Map<String, IntegrationManagement> managed = this.applicationContext.getBeansOfType(IntegrationManagement.class);
Map<String, IntegrationManagement> managed = this.applicationContext
.getBeansOfType(IntegrationManagement.class);
for (Entry<String, IntegrationManagement> entry : managed.entrySet()) {
IntegrationManagement bean = entry.getValue();
if (!bean.getOverrides().loggingConfigured) {
@@ -259,7 +261,8 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet
}
private void injectCaptor() {
Map<String, IntegrationManagement> managed = this.applicationContext.getBeansOfType(IntegrationManagement.class);
Map<String, IntegrationManagement> managed = this.applicationContext
.getBeansOfType(IntegrationManagement.class);
for (Entry<String, IntegrationManagement> entry : managed.entrySet()) {
IntegrationManagement bean = entry.getValue();
if (!bean.getOverrides().loggingConfigured) {
@@ -280,6 +283,30 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet
return bean;
}
@Override
public boolean requiresDestruction(Object bean) {
return bean instanceof MessageChannelMetrics ||
bean instanceof MessageHandlerMetrics ||
bean instanceof MessageSourceMetrics;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (bean instanceof MessageChannelMetrics) {
this.channelsByName.remove(beanName);
}
else if (bean instanceof MessageHandlerMetrics) {
if (this.handlersByName.remove(beanName) == null) {
this.handlersByName.remove(beanName + ".handler");
}
}
else if (bean instanceof MessageSourceMetrics) {
if (this.sourcesByName.remove(beanName) == null) {
this.sourcesByName.remove(beanName + ".source");
}
}
}
private Object doConfigureMetrics(Object bean, String name) {
if (bean instanceof MessageChannelMetrics) {
configureChannelMetrics(name, (MessageChannelMetrics) bean);