Fail explicitly in AOT transformations of instance supplier
It is by design not possible to generate code that handles bean definitions with user-provided instance suppliers because the JVM does not allow to get a stable reference reusable at runtime on the lambda or method reference in the code generated AOT. Before this commit, such instance supplier was ignored. After this commit, an IllegalArgumentException is thrown, allowing projects to be aware this is not supported and enforce related refactorings. The related issue gh-29555 describes how this limitation could be relaxed in the future. Closes gh-29556
This commit is contained in:
parent
047f660572
commit
ab0d1c395d
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -35,6 +35,7 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||||
import org.springframework.beans.factory.support.AutowireCandidateResolver;
|
import org.springframework.beans.factory.support.AutowireCandidateResolver;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.RegisteredBean;
|
import org.springframework.beans.factory.support.RegisteredBean;
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.javapoet.ClassName;
|
import org.springframework.javapoet.ClassName;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
@ -45,6 +46,7 @@ import org.springframework.util.StringUtils;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Sebastien Deleuze
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
* @see BeanDefinitionMethodGeneratorFactory
|
* @see BeanDefinitionMethodGeneratorFactory
|
||||||
*/
|
*/
|
||||||
|
|
@ -68,12 +70,17 @@ class BeanDefinitionMethodGenerator {
|
||||||
* @param registeredBean the registered bean
|
* @param registeredBean the registered bean
|
||||||
* @param currentPropertyName the current property name
|
* @param currentPropertyName the current property name
|
||||||
* @param aotContributions the AOT contributions
|
* @param aotContributions the AOT contributions
|
||||||
|
* @throws IllegalArgumentException if the bean definition defines an instance supplier since this can't be supported for code generation
|
||||||
*/
|
*/
|
||||||
BeanDefinitionMethodGenerator(
|
BeanDefinitionMethodGenerator(
|
||||||
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory,
|
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory,
|
||||||
RegisteredBean registeredBean, @Nullable String currentPropertyName,
|
RegisteredBean registeredBean, @Nullable String currentPropertyName,
|
||||||
List<BeanRegistrationAotContribution> aotContributions) {
|
List<BeanRegistrationAotContribution> aotContributions) {
|
||||||
|
|
||||||
|
RootBeanDefinition mbd = registeredBean.getMergedBeanDefinition();
|
||||||
|
if (mbd.getInstanceSupplier() != null) {
|
||||||
|
throw new IllegalArgumentException("Code generation is not supported for bean definitions declaring an instance supplier callback : " + mbd);
|
||||||
|
}
|
||||||
this.methodGeneratorFactory = methodGeneratorFactory;
|
this.methodGeneratorFactory = methodGeneratorFactory;
|
||||||
this.registeredBean = registeredBean;
|
this.registeredBean = registeredBean;
|
||||||
this.constructorOrFactoryMethod = registeredBean.resolveConstructorOrFactoryMethod();
|
this.constructorOrFactoryMethod = registeredBean.resolveConstructorOrFactoryMethod();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -58,6 +58,7 @@ import org.springframework.javapoet.MethodSpec;
|
||||||
import org.springframework.javapoet.ParameterizedTypeName;
|
import org.springframework.javapoet.ParameterizedTypeName;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link BeanDefinitionMethodGenerator} and
|
* Tests for {@link BeanDefinitionMethodGenerator} and
|
||||||
|
|
@ -65,6 +66,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Sebastien Deleuze
|
||||||
*/
|
*/
|
||||||
class BeanDefinitionMethodGeneratorTests {
|
class BeanDefinitionMethodGeneratorTests {
|
||||||
|
|
||||||
|
|
@ -491,6 +493,14 @@ class BeanDefinitionMethodGeneratorTests {
|
||||||
testBeanDefinitionMethodInCurrentFile(Boolean.class, beanDefinition);
|
testBeanDefinitionMethodInCurrentFile(Boolean.class, beanDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void throwExceptionWithInstanceSupplier() {
|
||||||
|
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(TestBean.class, TestBean::new));
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> new BeanDefinitionMethodGenerator(
|
||||||
|
this.methodGeneratorFactory, registeredBean, null,
|
||||||
|
Collections.emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
private void testBeanDefinitionMethodInCurrentFile(Class<?> targetType, RootBeanDefinition beanDefinition) {
|
private void testBeanDefinitionMethodInCurrentFile(Class<?> targetType, RootBeanDefinition beanDefinition) {
|
||||||
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(beanDefinition));
|
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(beanDefinition));
|
||||||
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
|
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue