Skip to content

Commit ab0d1c3

Browse files
committed
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 spring-projectsgh-29555 describes how this limitation could be relaxed in the future. Closes spring-projectsgh-29556
1 parent 047f660 commit ab0d1c3

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGenerator.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
import org.springframework.beans.factory.support.AutowireCandidateResolver;
3636
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3737
import org.springframework.beans.factory.support.RegisteredBean;
38+
import org.springframework.beans.factory.support.RootBeanDefinition;
3839
import org.springframework.core.MethodParameter;
3940
import org.springframework.javapoet.ClassName;
4041
import org.springframework.lang.Nullable;
@@ -45,6 +46,7 @@
4546
*
4647
* @author Phillip Webb
4748
* @author Stephane Nicoll
49+
* @author Sebastien Deleuze
4850
* @since 6.0
4951
* @see BeanDefinitionMethodGeneratorFactory
5052
*/
@@ -68,12 +70,17 @@ class BeanDefinitionMethodGenerator {
6870
* @param registeredBean the registered bean
6971
* @param currentPropertyName the current property name
7072
* @param aotContributions the AOT contributions
73+
* @throws IllegalArgumentException if the bean definition defines an instance supplier since this can't be supported for code generation
7174
*/
7275
BeanDefinitionMethodGenerator(
7376
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory,
7477
RegisteredBean registeredBean, @Nullable String currentPropertyName,
7578
List<BeanRegistrationAotContribution> aotContributions) {
7679

80+
RootBeanDefinition mbd = registeredBean.getMergedBeanDefinition();
81+
if (mbd.getInstanceSupplier() != null) {
82+
throw new IllegalArgumentException("Code generation is not supported for bean definitions declaring an instance supplier callback : " + mbd);
83+
}
7784
this.methodGeneratorFactory = methodGeneratorFactory;
7885
this.registeredBean = registeredBean;
7986
this.constructorOrFactoryMethod = registeredBean.resolveConstructorOrFactoryMethod();

spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,13 +58,15 @@
5858
import org.springframework.javapoet.ParameterizedTypeName;
5959

6060
import static org.assertj.core.api.Assertions.assertThat;
61+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
6162

6263
/**
6364
* Tests for {@link BeanDefinitionMethodGenerator} and
6465
* {@link DefaultBeanRegistrationCodeFragments}.
6566
*
6667
* @author Phillip Webb
6768
* @author Stephane Nicoll
69+
* @author Sebastien Deleuze
6870
*/
6971
class BeanDefinitionMethodGeneratorTests {
7072

@@ -491,6 +493,14 @@ void generateBeanDefinitionMethodWhenBeanIsOfPrimitiveType() {
491493
testBeanDefinitionMethodInCurrentFile(Boolean.class, beanDefinition);
492494
}
493495

496+
@Test
497+
void throwExceptionWithInstanceSupplier() {
498+
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(TestBean.class, TestBean::new));
499+
assertThatIllegalArgumentException().isThrownBy(() -> new BeanDefinitionMethodGenerator(
500+
this.methodGeneratorFactory, registeredBean, null,
501+
Collections.emptyList()));
502+
}
503+
494504
private void testBeanDefinitionMethodInCurrentFile(Class<?> targetType, RootBeanDefinition beanDefinition) {
495505
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(beanDefinition));
496506
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(

0 commit comments

Comments
 (0)