From 32f061a3e0ec4e990a0c8c3277e416a6daa73e27 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Thu, 22 Jun 2023 13:48:07 +0200 Subject: [PATCH] Polishing --- .../AbstractAutowireCapableBeanFactory.java | 9 +- .../support/DisposableBeanAdapter.java | 6 +- ...efinitionPropertiesCodeGeneratorTests.java | 116 ++++++++++-------- .../InitDestroyMethodLifecycleTests.java | 47 ++++--- 4 files changed, 100 insertions(+), 78 deletions(-) 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 0aa1f3fb4a9..82f6d2b05d9 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 @@ -1794,10 +1794,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } /** - * Give a bean a chance to react now all its properties are set, + * Give a bean a chance to initialize itself after all its properties are set, * and a chance to know about its owning bean factory (this object). - * This means checking whether the bean implements InitializingBean or defines - * a custom init method, and invoking the necessary callback(s) if it does. + *

This means checking whether the bean implements {@link InitializingBean} + * or defines any custom init methods, and invoking the necessary callback(s) + * if it does. * @param beanName the bean name in the factory (for debugging purposes) * @param bean the new bean instance we may need to initialize * @param mbd the merged bean definition that the bean was created with @@ -1860,7 +1861,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } if (logger.isTraceEnabled()) { - logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); + logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); } Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod, bean.getClass()); 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 0d2bc2adeb2..19c3e296312 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 @@ -252,15 +252,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { @Nullable - private Method determineDestroyMethod(String name) { + private Method determineDestroyMethod(String destroyMethodName) { try { Class beanClass = this.bean.getClass(); - Method destroyMethod = findDestroyMethod(beanClass, name); + Method destroyMethod = findDestroyMethod(beanClass, destroyMethodName); if (destroyMethod != null) { return destroyMethod; } for (Class beanInterface : beanClass.getInterfaces()) { - destroyMethod = findDestroyMethod(beanInterface, name); + destroyMethod = findDestroyMethod(beanInterface, destroyMethodName); if (destroyMethod != null) { return destroyMethod; } 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 e9e84fabbad..64cab3e0ea6 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 @@ -28,6 +28,8 @@ import java.util.function.Supplier; import javax.lang.model.element.Modifier; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.aot.generate.GeneratedClass; @@ -61,6 +63,8 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Phillip Webb * @author Stephane Nicoll * @author Olga Maciaszek-Sharma + * @author Sam Brannen + * @since 6.0 */ class BeanDefinitionPropertiesCodeGeneratorTests { @@ -212,56 +216,6 @@ class BeanDefinitionPropertiesCodeGeneratorTests { compile((actual, compiled) -> assertThat(actual.getRole()).isEqualTo(999)); } - @Test - void setInitMethodWhenSingleInitMethod() { - this.beanDefinition.setTargetType(InitDestroyBean.class); - this.beanDefinition.setInitMethodName("i1"); - compile((actual, compiled) -> assertThat(actual.getInitMethodNames()).containsExactly("i1")); - assertHasMethodInvokeHints(InitDestroyBean.class, "i1"); - } - - @Test - void setInitMethodWhenNoInitMethod() { - this.beanDefinition.setTargetType(InitDestroyBean.class); - compile((actual, compiled) -> assertThat(actual.getInitMethodNames()).isNull()); - } - - @Test - void setInitMethodWhenMultipleInitMethods() { - this.beanDefinition.setTargetType(InitDestroyBean.class); - this.beanDefinition.setInitMethodNames("i1", "i2"); - compile((actual, compiled) -> assertThat(actual.getInitMethodNames()).containsExactly("i1", "i2")); - assertHasMethodInvokeHints(InitDestroyBean.class, "i1", "i2"); - } - - @Test - void setDestroyMethodWhenDestroyInitMethod() { - this.beanDefinition.setTargetType(InitDestroyBean.class); - this.beanDefinition.setDestroyMethodName("d1"); - compile((actual, compiled) -> assertThat(actual.getDestroyMethodNames()).containsExactly("d1")); - assertHasMethodInvokeHints(InitDestroyBean.class, "d1"); - } - - @Test - void setDestroyMethodWhenNoDestroyMethod() { - this.beanDefinition.setTargetType(InitDestroyBean.class); - compile((actual, compiled) -> assertThat(actual.getDestroyMethodNames()).isNull()); - } - - @Test - void setDestroyMethodWhenMultipleDestroyMethods() { - this.beanDefinition.setTargetType(InitDestroyBean.class); - this.beanDefinition.setDestroyMethodNames("d1", "d2"); - compile((actual, compiled) -> assertThat(actual.getDestroyMethodNames()).containsExactly("d1", "d2")); - assertHasMethodInvokeHints(InitDestroyBean.class, "d1", "d2"); - } - - private void assertHasMethodInvokeHints(Class beanType, String... methodNames) { - assertThat(methodNames).allMatch(methodName -> RuntimeHintsPredicates.reflection() - .onMethod(beanType, methodName).invoke() - .test(this.generationContext.getRuntimeHints())); - } - @Test void constructorArgumentValuesWhenValues() { this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, String.class); @@ -419,6 +373,60 @@ class BeanDefinitionPropertiesCodeGeneratorTests { }); } + @Nested + class InitDestroyMethodTests { + + @BeforeEach + void setTargetType() { + beanDefinition.setTargetType(InitDestroyBean.class); + } + + @Test + void noInitMethod() { + compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).isNull()); + } + + @Test + void singleInitMethod() { + beanDefinition.setInitMethodName("init"); + compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).containsExactly("init")); + assertHasMethodInvokeHints(InitDestroyBean.class, "init"); + } + + @Test + void multipleInitMethods() { + beanDefinition.setInitMethodNames("init", "init2"); + compile((beanDef, compiled) -> assertThat(beanDef.getInitMethodNames()).containsExactly("init", "init2")); + assertHasMethodInvokeHints(InitDestroyBean.class, "init", "init2"); + } + + @Test + void noDestroyMethod() { + compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).isNull()); + } + + @Test + void singleDestroyMethod() { + beanDefinition.setDestroyMethodName("destroy"); + compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy")); + assertHasMethodInvokeHints(InitDestroyBean.class, "destroy"); + } + + @Test + void multipleDestroyMethods() { + beanDefinition.setDestroyMethodNames("destroy", "destroy2"); + compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy", "destroy2")); + assertHasMethodInvokeHints(InitDestroyBean.class, "destroy", "destroy2"); + } + + } + + private void assertHasMethodInvokeHints(Class beanType, String... methodNames) { + assertThat(methodNames).allMatch(methodName -> RuntimeHintsPredicates.reflection() + .onMethod(beanType, methodName).invoke() + .test(this.generationContext.getRuntimeHints())); + } + private void compile(BiConsumer result) { compile(attribute -> true, result); } @@ -450,16 +458,16 @@ class BeanDefinitionPropertiesCodeGeneratorTests { static class InitDestroyBean { - void i1() { + void init() { } - void i2() { + void init2() { } - void d1() { + void destroy() { } - void d2() { + void destroy2() { } } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/InitDestroyMethodLifecycleTests.java b/spring-context/src/test/java/org/springframework/context/annotation/InitDestroyMethodLifecycleTests.java index 8ac8784b6a7..5ece39b9393 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/InitDestroyMethodLifecycleTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/InitDestroyMethodLifecycleTests.java @@ -143,6 +143,7 @@ class InitDestroyMethodLifecycleTests { assertThat(bean.initMethods).as("init-methods").containsExactly( "PackagePrivateInitDestroyBean.postConstruct", "SubPackagePrivateInitDestroyBean.postConstruct", + "InitializingBean.afterPropertiesSet", "initMethod" ); @@ -150,6 +151,7 @@ class InitDestroyMethodLifecycleTests { assertThat(bean.destroyMethods).as("destroy-methods").containsExactly( "SubPackagePrivateInitDestroyBean.preDestroy", "PackagePrivateInitDestroyBean.preDestroy", + "DisposableBean.destroy", "destroyMethod" ); } @@ -191,12 +193,12 @@ class InitDestroyMethodLifecycleTests { InitializingBean, DisposableBean { @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { this.initMethods.add("InitializingBean.afterPropertiesSet"); } @Override - public void destroy() throws Exception { + public void destroy() { this.destroyMethods.add("DisposableBean.destroy"); } } @@ -206,11 +208,11 @@ class InitDestroyMethodLifecycleTests { final List initMethods = new ArrayList<>(); final List destroyMethods = new ArrayList<>(); - public void customInit() throws Exception { + public void customInit() { this.initMethods.add("customInit"); } - public void customDestroy() throws Exception { + public void customDestroy() { this.destroyMethods.add("customDestroy"); } } @@ -218,12 +220,12 @@ class InitDestroyMethodLifecycleTests { static class CustomAnnotatedPrivateInitDestroyBean extends CustomInitializingDisposableBean { @PostConstruct - private void customInit1() throws Exception { + private void customInit1() { this.initMethods.add("@PostConstruct.privateCustomInit1"); } @PreDestroy - private void customDestroy1() throws Exception { + private void customDestroy1() { this.destroyMethods.add("@PreDestroy.privateCustomDestroy1"); } } @@ -232,13 +234,13 @@ class InitDestroyMethodLifecycleTests { @PostConstruct @SuppressWarnings("unused") - private void customInit1() throws Exception { + private void customInit1() { this.initMethods.add("@PostConstruct.sameNameCustomInit1"); } @PreDestroy @SuppressWarnings("unused") - private void customDestroy1() throws Exception { + private void customDestroy1() { this.destroyMethods.add("@PreDestroy.sameNameCustomDestroy1"); } } @@ -247,12 +249,12 @@ class InitDestroyMethodLifecycleTests { implements InitializingBean, DisposableBean { @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { this.initMethods.add("afterPropertiesSet"); } @Override - public void destroy() throws Exception { + public void destroy() { this.destroyMethods.add("destroy"); } } @@ -260,12 +262,12 @@ class InitDestroyMethodLifecycleTests { static class CustomAnnotatedInitDestroyBean extends CustomInitializingDisposableBean { @PostConstruct - public void postConstruct() throws Exception { + public void postConstruct() { this.initMethods.add("postConstruct"); } @PreDestroy - public void preDestroy() throws Exception { + public void preDestroy() { this.destroyMethods.add("preDestroy"); } } @@ -274,13 +276,13 @@ class InitDestroyMethodLifecycleTests { @PostConstruct @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { this.initMethods.add("@PostConstruct.afterPropertiesSet"); } @PreDestroy @Override - public void destroy() throws Exception { + public void destroy() { this.destroyMethods.add("@PreDestroy.destroy"); } } @@ -292,18 +294,29 @@ class InitDestroyMethodLifecycleTests { @PostConstruct @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { this.initMethods.add("afterPropertiesSet"); } @PreDestroy @Override - public void destroy() throws Exception { + public void destroy() { this.destroyMethods.add("destroy"); } } - static class SubPackagePrivateInitDestroyBean extends PackagePrivateInitDestroyBean { + static class SubPackagePrivateInitDestroyBean extends PackagePrivateInitDestroyBean + implements InitializingBean, DisposableBean { + + @Override + public void afterPropertiesSet() { + this.initMethods.add("InitializingBean.afterPropertiesSet"); + } + + @Override + public void destroy() { + this.destroyMethods.add("DisposableBean.destroy"); + } @PostConstruct void postConstruct() {