Skip to content

Commit 1a0d406

Browse files
artembilanspring-builds
authored andcommitted
GH-9890: Fix ControlBusCommandRegistry for requiresDestruction()
Fixes: #9890 Issue link: #9890 The `DestructionAwareBeanPostProcessor.requiresDestruction()` defaults to `true`. As a result, beans that are not meant to be processed during the destroy lifecycle are being registered for the `AbstractBeanFactory#registerDisposableBeanIfNecessary`. for example, the `SimpleThreadScope` does not support destruction callbacks. In other words, the `DestructionAwareBeanPostProcessor.requiresDestruction()` contract is not merely for `DestructionAwareBeanPostProcessor` logic, but also has an effect on the whole `BeanFactory` * Implement `requiresDestruction()` in the `ControlBusCommandRegistry` for same filter as `registerControlBusCommands()` does right now. * Optimize behaviour using `MergedAnnotations` for the class instead of `AnnotationUtils.findAnnotation()` twice, which creates the mentioned `MergedAnnotations` internally. (cherry picked from commit 74cf59b)
1 parent 3857c77 commit 1a0d406

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

Diff for: spring-integration-core/src/main/java/org/springframework/integration/support/management/ControlBusCommandRegistry.java

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 the original author or authors.
2+
* Copyright 2024-2025 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.
@@ -37,6 +37,8 @@
3737
import org.springframework.context.Lifecycle;
3838
import org.springframework.core.MethodIntrospector;
3939
import org.springframework.core.annotation.AnnotationUtils;
40+
import org.springframework.core.annotation.MergedAnnotations;
41+
import org.springframework.core.annotation.RepeatableContainers;
4042
import org.springframework.expression.Expression;
4143
import org.springframework.expression.ExpressionParser;
4244
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -115,16 +117,17 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw
115117
* @param bean the bean for registration
116118
*/
117119
public void registerControlBusCommands(String beanName, Object bean) {
118-
Class<?> beanClass = bean.getClass();
119-
if (bean instanceof Lifecycle || bean instanceof CustomizableThreadCreator
120-
|| AnnotationUtils.findAnnotation(beanClass, ManagedResource.class) != null
121-
|| AnnotationUtils.findAnnotation(beanClass, IntegrationManagedResource.class) != null) {
122-
123-
ReflectionUtils.doWithMethods(beanClass, method -> populateExpressionForCommand(beanName, method),
120+
if (isBeanEligible(bean)) {
121+
ReflectionUtils.doWithMethods(bean.getClass(), method -> populateExpressionForCommand(beanName, method),
124122
CONTROL_BUS_METHOD_FILTER);
125123
}
126124
}
127125

126+
@Override
127+
public boolean requiresDestruction(Object bean) {
128+
return isBeanEligible(bean);
129+
}
130+
128131
@Override
129132
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
130133
this.controlBusCommands.remove(beanName);
@@ -221,6 +224,17 @@ private Expression buildExpressionForMethodToCall(CommandMethod commandMethod) {
221224
return buildExpressionForMethodToCall(commandMethod, methodForCommand.get());
222225
}
223226

227+
private static boolean isBeanEligible(Object bean) {
228+
MergedAnnotations mergedAnnotations =
229+
MergedAnnotations.from(bean.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY,
230+
RepeatableContainers.none());
231+
232+
return bean instanceof Lifecycle
233+
|| bean instanceof CustomizableThreadCreator
234+
|| mergedAnnotations.isPresent(ManagedResource.class)
235+
|| mergedAnnotations.isPresent(IntegrationManagedResource.class);
236+
}
237+
224238
private static Expression buildExpressionForMethodToCall(CommandMethod commandMethod, Method methodForCommand) {
225239
Assert.isTrue(CONTROL_BUS_METHOD_FILTER.matches(methodForCommand),
226240
() -> "The method '%s' is not valid Control Bus command".formatted(methodForCommand));

0 commit comments

Comments
 (0)