Update InitDestroyAnnotationBeanPostProcessor AOT support

Update `InitDestroyAnnotationBeanPostProcessor` so that it provides
AOT contributions via the `BeanRegistrationAotProcessor` interface.

See gh-28414
This commit is contained in:
Phillip Webb
2022-04-15 10:36:36 -07:00
parent 77c5a6f18d
commit 7664a54c93
2 changed files with 98 additions and 8 deletions

View File

@@ -19,6 +19,8 @@ package org.springframework.beans.factory.annotation;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.generator.BeanInstantiationContribution;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.factory.generator.lifecycle.Destroy;
import org.springframework.beans.testfixture.beans.factory.generator.lifecycle.Init;
@@ -34,13 +36,16 @@ import static org.mockito.Mockito.verifyNoInteractions;
* Tests for {@link InitDestroyAnnotationBeanPostProcessor}.
*
* @author Stephane Nicoll
* @author Phillip Webb
*/
class InitDestroyAnnotationBeanPostProcessorTests {
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
@Test
void contributeWithNoCallbackDoesNotMutateRootBeanDefinition() {
RootBeanDefinition beanDefinition = mock(RootBeanDefinition.class);
assertThat(createAotContributingBeanPostProcessor().contribute(
assertThat(createAotBeanPostProcessor().contribute(
beanDefinition, String.class, "test")).isNull();
verifyNoInteractions(beanDefinition);
}
@@ -87,15 +92,80 @@ class InitDestroyAnnotationBeanPostProcessorTests {
@Nullable
private BeanInstantiationContribution createContribution(RootBeanDefinition beanDefinition) {
InitDestroyAnnotationBeanPostProcessor bpp = createAotContributingBeanPostProcessor();
InitDestroyAnnotationBeanPostProcessor bpp = createAotBeanPostProcessor();
return bpp.contribute(beanDefinition, beanDefinition.getResolvableType().toClass(), "test");
}
private InitDestroyAnnotationBeanPostProcessor createAotContributingBeanPostProcessor() {
InitDestroyAnnotationBeanPostProcessor bpp = new InitDestroyAnnotationBeanPostProcessor();
bpp.setInitAnnotationType(Init.class);
bpp.setDestroyAnnotationType(Destroy.class);
return bpp;
@Test
void processAheadOfTimeWhenNoCallbackDoesNotMutateRootBeanDefinition() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(String.class);
processAheadOfTime(beanDefinition);
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition();
assertThat(mergedBeanDefinition.getInitMethodNames()).isNull();
assertThat(mergedBeanDefinition.getDestroyMethodNames()).isNull();
}
@Test
void processAheadOfTimeWhenHasInitDestroyAnnotationsAddsMethodNames() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(InitDestroyBean.class);
processAheadOfTime(beanDefinition);
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition();
assertThat(mergedBeanDefinition.getInitMethodNames()).containsExactly("initMethod");
assertThat(mergedBeanDefinition.getDestroyMethodNames()).containsExactly("destroyMethod");
}
@Test
void processAheadOfTimeWhenHasInitDestroyAnnotationsAndCustomDefinedMethodNamesAddsMethodNames() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(InitDestroyBean.class);
beanDefinition.setInitMethodName("customInitMethod");
beanDefinition.setDestroyMethodNames("customDestroyMethod");
processAheadOfTime(beanDefinition);
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition();
assertThat(mergedBeanDefinition.getInitMethodNames()).containsExactly("customInitMethod", "initMethod");
assertThat(mergedBeanDefinition.getDestroyMethodNames()).containsExactly("customDestroyMethod", "destroyMethod");
}
@Test
void processAheadOfTimeWhenHasInitDestroyAnnotationsAndOverlappingCustomDefinedMethodNamesFiltersDuplicates() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(InitDestroyBean.class);
beanDefinition.setInitMethodName("initMethod");
beanDefinition.setDestroyMethodNames("destroyMethod");
processAheadOfTime(beanDefinition);
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition();
assertThat(mergedBeanDefinition.getInitMethodNames()).containsExactly("initMethod");
assertThat(mergedBeanDefinition.getDestroyMethodNames()).containsExactly("destroyMethod");
}
@Test
void processAheadOfTimeWhenHasMultipleInitDestroyAnnotationsAddsAllMethodNames() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(MultiInitDestroyBean.class);
processAheadOfTime(beanDefinition);
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition();
assertThat(mergedBeanDefinition.getInitMethodNames()).containsExactly("initMethod", "anotherInitMethod");
assertThat(mergedBeanDefinition.getDestroyMethodNames()).containsExactly("anotherDestroyMethod", "destroyMethod");
}
private void processAheadOfTime(RootBeanDefinition beanDefinition) {
RegisteredBean registeredBean = registerBean(beanDefinition);
assertThat(createAotBeanPostProcessor().processAheadOfTime(registeredBean)).isNull();
}
private RegisteredBean registerBean(RootBeanDefinition beanDefinition) {
String beanName = "test";
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
RegisteredBean registeredBean = RegisteredBean.of(this.beanFactory, beanName);
return registeredBean;
}
private RootBeanDefinition getMergedBeanDefinition() {
return (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition("test");
}
private InitDestroyAnnotationBeanPostProcessor createAotBeanPostProcessor() {
InitDestroyAnnotationBeanPostProcessor beanPostProcessor = new InitDestroyAnnotationBeanPostProcessor();
beanPostProcessor.setInitAnnotationType(Init.class);
beanPostProcessor.setDestroyAnnotationType(Destroy.class);
return beanPostProcessor;
}
}