diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index a013c2bdce16..43e44308ae44 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -1830,6 +1830,12 @@ protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefi } } + if (Modifier.isPrivate(initMethod.getModifiers())) { + if (mbd.isExternallyManagedInitMethod(ClassUtils.getQualifiedMethodName(initMethod))) { + return; + } + } + if (logger.isTraceEnabled()) { logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); } 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 23354b6cccb2..38f74c92a5aa 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 @@ -19,6 +19,7 @@ import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; @@ -113,9 +114,8 @@ public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition be (bean instanceof AutoCloseable && CLOSE_METHOD_NAME.equals(destroyMethodNames[0])); if (!this.invokeAutoCloseable) { this.destroyMethodNames = destroyMethodNames; - Method[] destroyMethods = new Method[destroyMethodNames.length]; - for (int i = 0; i < destroyMethodNames.length; i++) { - String destroyMethodName = destroyMethodNames[i]; + List destroyMethods = new ArrayList<>(); + for (String destroyMethodName : destroyMethodNames) { Method destroyMethod = determineDestroyMethod(destroyMethodName); if (destroyMethod == null) { if (beanDefinition.isEnforceDestroyMethod()) { @@ -137,9 +137,14 @@ else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) { } destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod, bean.getClass()); } - destroyMethods[i] = destroyMethod; + if (destroyMethod != null && Modifier.isPrivate(destroyMethod.getModifiers())) { + if (beanDefinition.isExternallyManagedDestroyMethod(ClassUtils.getQualifiedMethodName(destroyMethod))) { + continue; + } + } + destroyMethods.add(destroyMethod); } - this.destroyMethods = destroyMethods; + this.destroyMethods = destroyMethods.toArray(new Method[destroyMethods.size()]); } } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/Spr3775InitDestroyLifecycleTests.java b/spring-context/src/test/java/org/springframework/context/annotation/Spr3775InitDestroyLifecycleTests.java index 821fffffcf57..93742e2a801f 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/Spr3775InitDestroyLifecycleTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/Spr3775InitDestroyLifecycleTests.java @@ -136,6 +136,30 @@ public void testJsr250AnnotationsWithShadowedMethods() { bean.destroyMethods); } + @Test + public void testJsr250AnnotationsWithCustomPrivateInitDestroyMethods() { + Class beanClass = CustomAnnotatedPrivateInitDestroyBean.class; + DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass, "customInit1", "customDestroy1"); + CustomAnnotatedPrivateInitDestroyBean bean = + (CustomAnnotatedPrivateInitDestroyBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN); + assertMethodOrdering("init-methods", Arrays.asList("privateCustomInit1","afterPropertiesSet"), bean.initMethods); + beanFactory.destroySingletons(); + assertMethodOrdering("destroy-methods", Arrays.asList("privateCustomDestroy1","destroy"), bean.destroyMethods); + } + + @Test + public void testJsr250AnnotationsWithCustomSameMethodNames() { + Class beanClass = CustomAnnotatedPrivateSameNameInitDestroyBean.class; + DefaultListableBeanFactory beanFactory = createBeanFactoryAndRegisterBean(beanClass, "customInit1", "customDestroy1"); + CustomAnnotatedPrivateSameNameInitDestroyBean bean = + (CustomAnnotatedPrivateSameNameInitDestroyBean) beanFactory.getBean(LIFECYCLE_TEST_BEAN); + assertMethodOrdering("init-methods", + Arrays.asList("privateCustomInit1","afterPropertiesSet","sameNameCustomInit1"), bean.initMethods); + beanFactory.destroySingletons(); + assertMethodOrdering("destroy-methods", + Arrays.asList("privateCustomDestroy1","destroy","sameNameCustomDestroy1"), bean.destroyMethods); + } + @Test public void testAllLifecycleMechanismsAtOnce() { Class beanClass = AllInOneBean.class; @@ -192,6 +216,31 @@ public void customDestroy() throws Exception { } } + public static class CustomAnnotatedPrivateInitDestroyBean extends CustomInitializingDisposableBean{ + + @PostConstruct + private void customInit1() throws Exception { + this.initMethods.add("privateCustomInit1"); + } + + @PreDestroy + private void customDestroy1() throws Exception { + this.destroyMethods.add("privateCustomDestroy1"); + } + + } + + public static class CustomAnnotatedPrivateSameNameInitDestroyBean extends CustomAnnotatedPrivateInitDestroyBean { + + private void customInit1() throws Exception { + this.initMethods.add("sameNameCustomInit1"); + } + + private void customDestroy1() throws Exception { + this.destroyMethods.add("sameNameCustomDestroy1"); + } + + } public static class CustomInitializingDisposableBean extends CustomInitDestroyBean implements InitializingBean, DisposableBean {