Skip to content

Commit

Permalink
Fix multiple invocation of lifecycle private method
Browse files Browse the repository at this point in the history
  • Loading branch information
vikeychen committed Feb 28, 2022
1 parent 27ee9cd commit a0e7773
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 5 deletions.
Expand Up @@ -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 + "'");
}
Expand Down
Expand Up @@ -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;

Expand Down Expand Up @@ -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<Method> destroyMethods = new ArrayList<>();
for (String destroyMethodName : destroyMethodNames) {
Method destroyMethod = determineDestroyMethod(destroyMethodName);
if (destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
Expand All @@ -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()]);
}
}

Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit a0e7773

Please sign in to comment.