Skip to content

Commit

Permalink
Polishing
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrannen committed Jun 22, 2023
1 parent 9b5cbc1 commit 32f061a
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 78 deletions.
Expand Up @@ -1794,10 +1794,11 @@ private void invokeAwareMethods(String beanName, Object bean) {
}

/**
* 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.
* <p>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
Expand Down Expand Up @@ -1860,7 +1861,7 @@ protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefi
}

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());

Expand Down
Expand Up @@ -252,15 +252,15 @@ else if (this.destroyMethodNames != null) {


@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;
}
Expand Down
Expand Up @@ -28,6 +28,8 @@

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;
Expand Down Expand Up @@ -61,6 +63,8 @@
* @author Phillip Webb
* @author Stephane Nicoll
* @author Olga Maciaszek-Sharma
* @author Sam Brannen
* @since 6.0
*/
class BeanDefinitionPropertiesCodeGeneratorTests {

Expand Down Expand Up @@ -212,56 +216,6 @@ void setRoleWhenOther() {
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);
Expand Down Expand Up @@ -419,6 +373,60 @@ void multipleItems() {
});
}

@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<RootBeanDefinition, Compiled> result) {
compile(attribute -> true, result);
}
Expand Down Expand Up @@ -450,16 +458,16 @@ private void compile(Predicate<String> attributeFilter, BiConsumer<RootBeanDefin

static class InitDestroyBean {

void i1() {
void init() {
}

void i2() {
void init2() {
}

void d1() {
void destroy() {
}

void d2() {
void destroy2() {
}

}
Expand Down
Expand Up @@ -143,13 +143,15 @@ void jakartaAnnotationsCustomPackagePrivateInitDestroyMethodsWithTheSameMethodNa
assertThat(bean.initMethods).as("init-methods").containsExactly(
"PackagePrivateInitDestroyBean.postConstruct",
"SubPackagePrivateInitDestroyBean.postConstruct",
"InitializingBean.afterPropertiesSet",
"initMethod"
);

beanFactory.destroySingletons();
assertThat(bean.destroyMethods).as("destroy-methods").containsExactly(
"SubPackagePrivateInitDestroyBean.preDestroy",
"PackagePrivateInitDestroyBean.preDestroy",
"DisposableBean.destroy",
"destroyMethod"
);
}
Expand Down Expand Up @@ -191,12 +193,12 @@ static class InitializingDisposableWithShadowedMethodsBean extends InitDestroyBe
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");
}
}
Expand All @@ -206,24 +208,24 @@ static class CustomInitDestroyBean {
final List<String> initMethods = new ArrayList<>();
final List<String> 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");
}
}

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");
}
}
Expand All @@ -232,13 +234,13 @@ static class CustomAnnotatedPrivateSameNameInitDestroyBean extends CustomAnnotat

@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");
}
}
Expand All @@ -247,25 +249,25 @@ static class CustomInitializingDisposableBean extends CustomInitDestroyBean
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");
}
}

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");
}
}
Expand All @@ -274,13 +276,13 @@ static class CustomAnnotatedInitDestroyWithShadowedMethodsBean extends CustomIni

@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");
}
}
Expand All @@ -292,18 +294,29 @@ static class AllInOneBean implements InitializingBean, DisposableBean {

@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() {
Expand Down

0 comments on commit 32f061a

Please sign in to comment.