Update InitDestroyAnnotationBeanPostProcessor AOT support
Update `InitDestroyAnnotationBeanPostProcessor` so that it provides AOT contributions via the `BeanRegistrationAotProcessor` interface. See gh-28414
This commit is contained in:
parent
77c5a6f18d
commit
7664a54c93
|
|
@ -39,10 +39,13 @@ import org.apache.commons.logging.LogFactory;
|
|||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
|
||||
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.AotContributingBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContribution;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
|
|
@ -77,13 +80,15 @@ import org.springframework.util.ReflectionUtils;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 2.5
|
||||
* @see #setInitAnnotationType
|
||||
* @see #setDestroyAnnotationType
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareBeanPostProcessor,
|
||||
MergedBeanDefinitionPostProcessor, AotContributingBeanPostProcessor, PriorityOrdered, Serializable {
|
||||
MergedBeanDefinitionPostProcessor, AotContributingBeanPostProcessor, BeanRegistrationAotProcessor,
|
||||
PriorityOrdered, Serializable {
|
||||
|
||||
private final transient LifecycleMetadata emptyLifecycleMetadata =
|
||||
new LifecycleMetadata(Object.class, Collections.emptyList(), Collections.emptyList()) {
|
||||
|
|
@ -170,6 +175,21 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
|
||||
RootBeanDefinition beanDefinition = registeredBean.getMergedBeanDefinition();
|
||||
LifecycleMetadata metadata = findInjectionMetadata(beanDefinition, registeredBean.getBeanClass());
|
||||
if (!CollectionUtils.isEmpty(metadata.initMethods)) {
|
||||
String[] initMethodNames = safeMerge(beanDefinition.getInitMethodNames(), metadata.initMethods);
|
||||
beanDefinition.setInitMethodNames(initMethodNames);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(metadata.destroyMethods)) {
|
||||
String[] destroyMethodNames = safeMerge(beanDefinition.getDestroyMethodNames(), metadata.destroyMethods);
|
||||
beanDefinition.setDestroyMethodNames(destroyMethodNames);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private LifecycleMetadata findInjectionMetadata(RootBeanDefinition beanDefinition, Class<?> beanType) {
|
||||
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
|
||||
metadata.checkConfigMembers(beanDefinition);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue