diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java index 85a75c8456c..6b7da1d5b2c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java @@ -41,9 +41,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; -import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; -import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -160,30 +158,20 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB @Override public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { - AbstractBeanDefinition beanDefinition = getOriginalBeanDefinition(registeredBean); - if (beanDefinition != null) { - RootBeanDefinition mergedBeanDefinition = registeredBean.getMergedBeanDefinition(); - beanDefinition.resolveDestroyMethodIfNecessary(); - LifecycleMetadata metadata = findInjectionMetadata(mergedBeanDefinition, registeredBean.getBeanClass()); - if (!CollectionUtils.isEmpty(metadata.initMethods)) { - String[] initMethodNames = safeMerge(beanDefinition.getInitMethodNames(), metadata.initMethods); - beanDefinition.setInitMethodNames(initMethodNames); - } - if (!CollectionUtils.isEmpty(metadata.destroyMethods)) { - String[] destroyMethodNames = safeMerge(beanDefinition.getDestroyMethodNames(), metadata.destroyMethods); - beanDefinition.setDestroyMethodNames(destroyMethodNames); - } - registeredBean.getBeanFactory().clearMetadataCache(); + RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition(); + beanDefinition.resolveDestroyMethodIfNecessary(); + LifecycleMetadata metadata = findInjectionMetadata(beanDefinition, registeredBean.getBeanClass()); + if (!CollectionUtils.isEmpty(metadata.initMethods)) { + String[] initMethodNames = safeMerge(beanDefinition.getInitMethodNames(), metadata.initMethods); + beanDefinition.setInitMethodNames(initMethodNames); + } + if (!CollectionUtils.isEmpty(metadata.destroyMethods)) { + String[] destroyMethodNames = safeMerge(beanDefinition.getDestroyMethodNames(), metadata.destroyMethods); + beanDefinition.setDestroyMethodNames(destroyMethodNames); } return null; } - @Nullable - private AbstractBeanDefinition getOriginalBeanDefinition(RegisteredBean registeredBean) { - BeanDefinition beanDefinition = registeredBean.getBeanFactory().getBeanDefinition(registeredBean.getBeanName()); - return (beanDefinition instanceof AbstractBeanDefinition abd ? abd : null); - } - private LifecycleMetadata findInjectionMetadata(RootBeanDefinition beanDefinition, Class beanType) { LifecycleMetadata metadata = findLifecycleMetadata(beanType); metadata.checkConfigMembers(beanDefinition); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java index ef223e569e7..201e3d27187 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java @@ -1186,14 +1186,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess } } - /** - * Resolve the inferred destroy method if necessary. - * @since 6.0 - */ - public void resolveDestroyMethodIfNecessary() { - setDestroyMethodNames(DisposableBeanAdapter - .inferDestroyMethodsIfNecessary(getResolvableType().toClass(), this)); - } /** * Public declaration of Object's {@code clone()} method. diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java index 91fa30031bb..374e65aa0d5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java @@ -344,14 +344,13 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { * interfaces, reflectively calling the "close" method on implementing beans as well. */ @Nullable - static String[] inferDestroyMethodsIfNecessary(Class target, AbstractBeanDefinition beanDefinition) { + static String[] inferDestroyMethodsIfNecessary(Class target, RootBeanDefinition beanDefinition) { String[] destroyMethodNames = beanDefinition.getDestroyMethodNames(); if (destroyMethodNames != null && destroyMethodNames.length > 1) { return destroyMethodNames; } - String destroyMethodName = (beanDefinition instanceof RootBeanDefinition rbd - ? rbd.resolvedDestroyMethodName : null); + String destroyMethodName = beanDefinition.resolvedDestroyMethodName; if (destroyMethodName == null) { destroyMethodName = beanDefinition.getDestroyMethodName(); boolean autoCloseable = (AutoCloseable.class.isAssignableFrom(target)); @@ -379,9 +378,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { } } } - if (beanDefinition instanceof RootBeanDefinition rbd) { - rbd.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : ""); - } + beanDefinition.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : ""); } return (StringUtils.hasLength(destroyMethodName) ? new String[] {destroyMethodName} : null); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java index 72fd154fe38..7a50e6f0159 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java @@ -550,6 +550,15 @@ public class RootBeanDefinition extends AbstractBeanDefinition { } } + /** + * Resolve the inferred destroy method if necessary. + * @since 6.0 + */ + public void resolveDestroyMethodIfNecessary() { + setDestroyMethodNames(DisposableBeanAdapter + .inferDestroyMethodsIfNecessary(getResolvableType().toClass(), this)); + } + /** * Register an externally managed configuration destruction method — * for example, a method annotated with JSR-250's diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessorTests.java index 09f40c10f05..9856e9d1cf9 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessorTests.java @@ -90,19 +90,6 @@ class InitDestroyAnnotationBeanPostProcessorTests { assertThat(mergedBeanDefinition.getDestroyMethodNames()).containsExactly("close"); } - @Test - void processAheadOfTimeWhenHasInferredDestroyMethodIsRetainedIfMergedBeanDefinitionIsStale() { - RootBeanDefinition beanDefinition = new RootBeanDefinition(InferredDestroyBean.class); - beanDefinition.setDestroyMethodNames(AbstractBeanDefinition.INFER_METHOD); - processAheadOfTime(beanDefinition); - RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(); - assertThat(mergedBeanDefinition.getInitMethodNames()).isNull(); - assertThat(mergedBeanDefinition.getDestroyMethodNames()).containsExactly("close"); - RootBeanDefinition originalBeanDefinition = (RootBeanDefinition) this.beanFactory.getBeanDefinition("test"); - assertThat(originalBeanDefinition.getInitMethodNames()).isNull(); - assertThat(originalBeanDefinition.getDestroyMethodNames()).containsExactly("close"); - } - @Test void processAheadOfTimeWhenHasInferredDestroyMethodAndNoCandidateDoesNotMutateRootBeanDefinition() { RootBeanDefinition beanDefinition = new RootBeanDefinition(NoInitDestroyBean.class);