Make sure interface method has hints for init/destroy invocation

This commit matches the behavior of the core container when it
invokes a custom init or destroy method. If the custom method is an
interface implementation, the core container attempts to invoke the
method that's defined on the interface. This commit makes sure to also
register a hint for the interface method.

Closes gh-31819
This commit is contained in:
Stéphane Nicoll 2023-12-12 14:43:58 +01:00
parent c0683cd30b
commit c75c0ae2d5
2 changed files with 48 additions and 0 deletions

View File

@ -166,6 +166,10 @@ class BeanDefinitionPropertiesCodeGenerator {
Method method = ReflectionUtils.findMethod(methodDeclaringClass, methodName);
if (method != null) {
this.hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
Method interfaceMethod = ClassUtils.getInterfaceMethodIfPossible(method, beanUserClass);
if (!interfaceMethod.equals(method)) {
this.hints.reflection().registerMethod(interfaceMethod, ExecutableMode.INVOKE);
}
}
}

View File

@ -457,6 +457,15 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
assertHasMethodInvokeHints(InitDestroyBean.class, "init");
}
@Test
void singleInitMethodFromInterface() {
beanDefinition.setTargetType(InitializableTestBean.class);
beanDefinition.setInitMethodName("initialize");
compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).containsExactly("initialize"));
assertHasMethodInvokeHints(InitializableTestBean.class, "initialize");
assertHasMethodInvokeHints(Initializable.class, "initialize");
}
@Test
void privateInitMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
@ -489,6 +498,16 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
assertReflectionOnPublisher();
}
@Test
void singleDestroyMethodFromInterface() {
beanDefinition.setTargetType(DisposableTestBean.class);
beanDefinition.setDestroyMethodName("dispose");
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("dispose"));
assertHasMethodInvokeHints(DisposableTestBean.class, "dispose");
assertHasMethodInvokeHints(Disposable.class, "dispose");
assertReflectionOnPublisher();
}
@Test
void privateDestroyMethod() {
beanDefinition.setTargetType(InitDestroyBean.class);
@ -572,6 +591,31 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
}
interface Initializable {
void initialize();
}
static class InitializableTestBean implements Initializable {
@Override
public void initialize() {
}
}
interface Disposable {
void dispose();
}
static class DisposableTestBean implements Disposable {
@Override
public void dispose() {
}
}
static class PropertyValuesBean {
private Class<?> test;