diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java index a21e017365..2f474de6a5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java @@ -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); + } } } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java index 2c2667b3c2..1e473202a7 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java @@ -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;