Browse Source

Add generics to BeanInstanceSupplier

Update `BeanInstanceSupplier` to support a generic type.

See gh-28748
pull/28852/head
Phillip Webb 4 years ago
parent
commit
cfb61d2a17
  1. 51
      spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java
  2. 2
      spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationsAotContribution.java
  3. 87
      spring-beans/src/main/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGenerator.java
  4. 41
      spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java
  5. 42
      spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanInstanceSupplierTests.java
  6. 6
      spring-beans/src/test/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGeneratorTests.java
  7. 32
      spring-beans/src/test/java/org/springframework/beans/factory/aot/TestBeanConfiguration.java

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

@ -79,21 +79,22 @@ import org.springframework.util.function.ThrowingSupplier; @@ -79,21 +79,22 @@ import org.springframework.util.function.ThrowingSupplier;
* @author Phillip Webb
* @author Stephane Nicoll
* @since 6.0
* @param <T> the type of instance supplied by this supplier
* @see AutowiredArguments
*/
public final class BeanInstanceSupplier extends AutowiredElementResolver implements InstanceSupplier<Object> {
public final class BeanInstanceSupplier<T> extends AutowiredElementResolver implements InstanceSupplier<T> {
private final ExecutableLookup lookup;
@Nullable
private final ThrowingBiFunction<RegisteredBean, AutowiredArguments, Object> generator;
private final ThrowingBiFunction<RegisteredBean, AutowiredArguments, T> generator;
@Nullable
private final String[] shortcuts;
private BeanInstanceSupplier(ExecutableLookup lookup,
@Nullable ThrowingBiFunction<RegisteredBean, AutowiredArguments, Object> generator,
@Nullable ThrowingBiFunction<RegisteredBean, AutowiredArguments, T> generator,
@Nullable String[] shortcuts) {
this.lookup = lookup;
this.generator = generator;
@ -103,28 +104,30 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme @@ -103,28 +104,30 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme
/**
* Create a {@link BeanInstanceSupplier} that resolves
* arguments for the specified bean constructor.
* @param <T> the type of instance supplied
* @param parameterTypes the constructor parameter types
* @return a new {@link BeanInstanceSupplier} instance
*/
public static BeanInstanceSupplier forConstructor(
public static <T> BeanInstanceSupplier<T> forConstructor(
Class<?>... parameterTypes) {
Assert.notNull(parameterTypes, "'parameterTypes' must not be null");
Assert.noNullElements(parameterTypes,
"'parameterTypes' must not contain null elements");
return new BeanInstanceSupplier(
return new BeanInstanceSupplier<>(
new ConstructorLookup(parameterTypes), null, null);
}
/**
* Create a new {@link BeanInstanceSupplier} that
* resolves arguments for the specified factory method.
* @param <T> the type of instance supplied
* @param declaringClass the class that declares the factory method
* @param methodName the factory method name
* @param parameterTypes the factory method parameter types
* @return a new {@link BeanInstanceSupplier} instance
*/
public static BeanInstanceSupplier forFactoryMethod(
public static <T> BeanInstanceSupplier<T> forFactoryMethod(
Class<?> declaringClass, String methodName, Class<?>... parameterTypes) {
Assert.notNull(declaringClass, "'declaringClass' must not be null");
@ -132,7 +135,7 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme @@ -132,7 +135,7 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme
Assert.notNull(parameterTypes, "'parameterTypes' must not be null");
Assert.noNullElements(parameterTypes,
"'parameterTypes' must not contain null elements");
return new BeanInstanceSupplier(
return new BeanInstanceSupplier<>(
new FactoryMethodLookup(declaringClass, methodName, parameterTypes),
null, null);
}
@ -151,10 +154,10 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme @@ -151,10 +154,10 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme
* @return a new {@link BeanInstanceSupplier} instance with the specified
* generator
*/
public BeanInstanceSupplier withGenerator(
ThrowingBiFunction<RegisteredBean, AutowiredArguments, Object> generator) {
public BeanInstanceSupplier<T> withGenerator(
ThrowingBiFunction<RegisteredBean, AutowiredArguments, T> generator) {
Assert.notNull(generator, "'generator' must not be null");
return new BeanInstanceSupplier(this.lookup, generator, this.shortcuts);
return new BeanInstanceSupplier<T>(this.lookup, generator, this.shortcuts);
}
/**
@ -165,10 +168,10 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme @@ -165,10 +168,10 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme
* @return a new {@link BeanInstanceSupplier} instance with the specified
* generator
*/
public BeanInstanceSupplier withGenerator(
ThrowingFunction<RegisteredBean, Object> generator) {
public BeanInstanceSupplier<T> withGenerator(
ThrowingFunction<RegisteredBean, T> generator) {
Assert.notNull(generator, "'generator' must not be null");
return new BeanInstanceSupplier(this.lookup, (registeredBean, args) ->
return new BeanInstanceSupplier<>(this.lookup, (registeredBean, args) ->
generator.apply(registeredBean), this.shortcuts);
}
@ -180,9 +183,9 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme @@ -180,9 +183,9 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme
* @return a new {@link BeanInstanceSupplier} instance with the specified
* generator
*/
public BeanInstanceSupplier withGenerator(ThrowingSupplier<Object> generator) {
public BeanInstanceSupplier<T> withGenerator(ThrowingSupplier<T> generator) {
Assert.notNull(generator, "'generator' must not be null");
return new BeanInstanceSupplier(this.lookup, (registeredBean, args) ->
return new BeanInstanceSupplier<>(this.lookup, (registeredBean, args) ->
generator.get(), this.shortcuts);
}
@ -194,22 +197,19 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme @@ -194,22 +197,19 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme
* @return a new {@link BeanInstanceSupplier} instance
* that uses the shortcuts
*/
public BeanInstanceSupplier withShortcuts(String... beanNames) {
return new BeanInstanceSupplier(this.lookup, this.generator, beanNames);
public BeanInstanceSupplier<T> withShortcuts(String... beanNames) {
return new BeanInstanceSupplier<T>(this.lookup, this.generator, beanNames);
}
@Override
public Object get(RegisteredBean registeredBean) throws Exception {
public T get(RegisteredBean registeredBean) throws Exception {
Assert.notNull(registeredBean, "'registeredBean' must not be null");
Executable executable = this.lookup.get(registeredBean);
AutowiredArguments arguments = resolveArguments(registeredBean, executable);
if (this.generator != null) {
return this.generator.apply(registeredBean, arguments);
}
else {
return instantiate(registeredBean.getBeanFactory(), executable,
arguments.toArray());
}
return instantiate(registeredBean.getBeanFactory(), executable, arguments.toArray());
}
@Nullable
@ -351,15 +351,16 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme @@ -351,15 +351,16 @@ public final class BeanInstanceSupplier extends AutowiredElementResolver impleme
}
}
private Object instantiate(ConfigurableBeanFactory beanFactory, Executable executable,
@SuppressWarnings("unchecked")
private T instantiate(ConfigurableBeanFactory beanFactory, Executable executable,
Object[] arguments) {
try {
if (executable instanceof Constructor<?> constructor) {
return instantiate(constructor, arguments);
return (T) instantiate(constructor, arguments);
}
if (executable instanceof Method method) {
return instantiate(beanFactory, method, arguments);
return (T) instantiate(beanFactory, method, arguments);
}
}
catch (Exception ex) {

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

@ -41,10 +41,8 @@ import org.springframework.javapoet.MethodSpec; @@ -41,10 +41,8 @@ import org.springframework.javapoet.MethodSpec;
class BeanRegistrationsAotContribution
implements BeanFactoryInitializationAotContribution {
private static final String BEAN_FACTORY_PARAMETER_NAME = "beanFactory";
private final Map<String, BeanDefinitionMethodGenerator> registrations;

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

@ -37,6 +37,7 @@ import org.springframework.javapoet.ClassName; @@ -37,6 +37,7 @@ import org.springframework.javapoet.ClassName;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.CodeBlock.Builder;
import org.springframework.javapoet.MethodSpec;
import org.springframework.javapoet.ParameterizedTypeName;
import org.springframework.util.ClassUtils;
import org.springframework.util.function.ThrowingSupplier;
@ -108,7 +109,8 @@ class InstanceSupplierCodeGenerator { @@ -108,7 +109,8 @@ class InstanceSupplierCodeGenerator {
private CodeBlock generateCodeForConstructor(RegisteredBean registeredBean,
Constructor<?> constructor) {
String name = registeredBean.getBeanName();
String beanName = registeredBean.getBeanName();
Class<?> beanClass = registeredBean.getBeanClass();
Class<?> declaringClass = ClassUtils
.getUserClass(constructor.getDeclaringClass());
boolean dependsOnBean = ClassUtils.isInnerClass(declaringClass);
@ -116,13 +118,13 @@ class InstanceSupplierCodeGenerator { @@ -116,13 +118,13 @@ class InstanceSupplierCodeGenerator {
constructor);
if (accessVisibility == AccessVisibility.PUBLIC
|| accessVisibility == AccessVisibility.PACKAGE_PRIVATE) {
return generateCodeForAccessibleConstructor(name, constructor, dependsOnBean,
declaringClass);
return generateCodeForAccessibleConstructor(beanName, beanClass, constructor,
dependsOnBean, declaringClass);
}
return generateCodeForInaccessibleConstructor(name, constructor, dependsOnBean);
return generateCodeForInaccessibleConstructor(beanName, beanClass, constructor, dependsOnBean);
}
private CodeBlock generateCodeForAccessibleConstructor(String name,
private CodeBlock generateCodeForAccessibleConstructor(String beanName, Class<?> beanClass,
Constructor<?> constructor, boolean dependsOnBean, Class<?> declaringClass) {
this.generationContext.getRuntimeHints().reflection()
@ -139,37 +141,36 @@ class InstanceSupplierCodeGenerator { @@ -139,37 +141,36 @@ class InstanceSupplierCodeGenerator {
declaringClass);
}
GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method ->
buildGetInstanceMethodForConstructor(method, name, constructor,
buildGetInstanceMethodForConstructor(method, beanName, beanClass, constructor,
declaringClass, dependsOnBean, PRIVATE_STATIC));
return generateReturnStatement(generatedMethod);
}
private CodeBlock generateCodeForInaccessibleConstructor(String name,
Constructor<?> constructor, boolean dependsOnBean) {
private CodeBlock generateCodeForInaccessibleConstructor(String beanName,
Class<?> beanClass, Constructor<?> constructor, boolean dependsOnBean) {
this.generationContext.getRuntimeHints().reflection()
.registerConstructor(constructor);
GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method -> {
method.addJavadoc("Get the bean instance supplier for '$L'.", name);
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(PRIVATE_STATIC);
method.returns(BeanInstanceSupplier.class);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
int parameterOffset = (!dependsOnBean) ? 0 : 1;
method.addStatement(
generateResolverForConstructor(constructor, parameterOffset));
method.addStatement(generateResolverForConstructor(beanClass, constructor, parameterOffset));
});
return generateReturnStatement(generatedMethod);
}
private void buildGetInstanceMethodForConstructor(MethodSpec.Builder method,
String name, Constructor<?> constructor, Class<?> declaringClass,
String beanName, Class<?> beanClass, Constructor<?> constructor, Class<?> declaringClass,
boolean dependsOnBean, javax.lang.model.element.Modifier... modifiers) {
method.addJavadoc("Get the bean instance supplier for '$L'.", name);
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(modifiers);
method.returns(BeanInstanceSupplier.class);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
int parameterOffset = (!dependsOnBean) ? 0 : 1;
CodeBlock.Builder code = CodeBlock.builder();
code.add(generateResolverForConstructor(constructor, parameterOffset));
code.add(generateResolverForConstructor(beanClass, constructor, parameterOffset));
boolean hasArguments = constructor.getParameterCount() > 0;
CodeBlock arguments = hasArguments
? new AutowiredArgumentsCodeGenerator(declaringClass, constructor)
@ -181,13 +182,13 @@ class InstanceSupplierCodeGenerator { @@ -181,13 +182,13 @@ class InstanceSupplierCodeGenerator {
method.addStatement(code.build());
}
private CodeBlock generateResolverForConstructor(Constructor<?> constructor,
int parameterOffset) {
private CodeBlock generateResolverForConstructor(Class<?> beanClass,
Constructor<?> constructor, int parameterOffset) {
CodeBlock parameterTypes = generateParameterTypesCode(
constructor.getParameterTypes(), parameterOffset);
return CodeBlock.of("return $T.forConstructor($L)",
BeanInstanceSupplier.class, parameterTypes);
return CodeBlock.of("return $T.<$T>forConstructor($L)",
BeanInstanceSupplier.class, beanClass, parameterTypes);
}
private CodeBlock generateNewInstanceCodeForConstructor(boolean dependsOnBean,
@ -204,7 +205,8 @@ class InstanceSupplierCodeGenerator { @@ -204,7 +205,8 @@ class InstanceSupplierCodeGenerator {
private CodeBlock generateCodeForFactoryMethod(RegisteredBean registeredBean,
Method factoryMethod) {
String name = registeredBean.getBeanName();
String beanName = registeredBean.getBeanName();
Class<?> beanClass = registeredBean.getBeanClass();
Class<?> declaringClass = ClassUtils
.getUserClass(factoryMethod.getDeclaringClass());
boolean dependsOnBean = !Modifier.isStatic(factoryMethod.getModifiers());
@ -212,55 +214,56 @@ class InstanceSupplierCodeGenerator { @@ -212,55 +214,56 @@ class InstanceSupplierCodeGenerator {
factoryMethod);
if (accessVisibility == AccessVisibility.PUBLIC
|| accessVisibility == AccessVisibility.PACKAGE_PRIVATE) {
return generateCodeForAccessibleFactoryMethod(name, factoryMethod,
return generateCodeForAccessibleFactoryMethod(beanName, beanClass, factoryMethod,
declaringClass, dependsOnBean);
}
return generateCodeForInaccessibleFactoryMethod(name, factoryMethod,
return generateCodeForInaccessibleFactoryMethod(beanName, beanClass, factoryMethod,
declaringClass);
}
private CodeBlock generateCodeForAccessibleFactoryMethod(String name,
Method factoryMethod, Class<?> declaringClass, boolean dependsOnBean) {
private CodeBlock generateCodeForAccessibleFactoryMethod(String beanName,
Class<?> beanClass, Method factoryMethod, Class<?> declaringClass, boolean dependsOnBean) {
this.generationContext.getRuntimeHints().reflection()
.registerMethod(factoryMethod, INTROSPECT);
if (!dependsOnBean && factoryMethod.getParameterCount() == 0) {
CodeBlock.Builder code = CodeBlock.builder();
code.add("$T.forFactoryMethod($T.class, $S)", BeanInstanceSupplier.class,
declaringClass, factoryMethod.getName());
code.add("$T.<$T>forFactoryMethod($T.class, $S)", BeanInstanceSupplier.class,
beanClass, declaringClass, factoryMethod.getName());
code.add(".withGenerator($T::$L)", declaringClass, factoryMethod.getName());
return code.build();
}
GeneratedMethod getInstanceMethod = generateGetInstanceSupplierMethod(method ->
buildGetInstanceMethodForFactoryMethod(method, name, factoryMethod,
buildGetInstanceMethodForFactoryMethod(method, beanName, beanClass, factoryMethod,
declaringClass, dependsOnBean, PRIVATE_STATIC));
return generateReturnStatement(getInstanceMethod);
}
private CodeBlock generateCodeForInaccessibleFactoryMethod(String name,
private CodeBlock generateCodeForInaccessibleFactoryMethod(String beanName, Class<?> beanClass,
Method factoryMethod, Class<?> declaringClass) {
this.generationContext.getRuntimeHints().reflection()
.registerMethod(factoryMethod);
GeneratedMethod getInstanceMethod = generateGetInstanceSupplierMethod(method -> {
method.addJavadoc("Get the bean instance supplier for '$L'.", name);
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(PRIVATE_STATIC);
method.returns(BeanInstanceSupplier.class);
method.addStatement(generateInstanceSupplierForFactoryMethod(factoryMethod,
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
method.addStatement(generateInstanceSupplierForFactoryMethod(beanClass, factoryMethod,
declaringClass, factoryMethod.getName()));
});
return generateReturnStatement(getInstanceMethod);
}
private void buildGetInstanceMethodForFactoryMethod(MethodSpec.Builder method,
String name, Method factoryMethod, Class<?> declaringClass,
String beanName, Class<?> beanClass, Method factoryMethod, Class<?> declaringClass,
boolean dependsOnBean, javax.lang.model.element.Modifier... modifiers) {
String factoryMethodName = factoryMethod.getName();
method.addJavadoc("Get the bean instance supplier for '$L'.", name);
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(modifiers);
method.returns(BeanInstanceSupplier.class);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
CodeBlock.Builder code = CodeBlock.builder();
code.add(generateInstanceSupplierForFactoryMethod(factoryMethod, declaringClass, factoryMethodName));
code.add(generateInstanceSupplierForFactoryMethod(beanClass, factoryMethod, declaringClass, factoryMethodName));
boolean hasArguments = factoryMethod.getParameterCount() > 0;
CodeBlock arguments = hasArguments
? new AutowiredArgumentsCodeGenerator(declaringClass, factoryMethod)
@ -272,18 +275,18 @@ class InstanceSupplierCodeGenerator { @@ -272,18 +275,18 @@ class InstanceSupplierCodeGenerator {
method.addStatement(code.build());
}
private CodeBlock generateInstanceSupplierForFactoryMethod(Method factoryMethod,
Class<?> declaringClass, String factoryMethodName) {
private CodeBlock generateInstanceSupplierForFactoryMethod(Class<?> beanClass,
Method factoryMethod, Class<?> declaringClass, String factoryMethodName) {
if (factoryMethod.getParameterCount() == 0) {
return CodeBlock.of("return $T.forFactoryMethod($T.class, $S)",
BeanInstanceSupplier.class, declaringClass,
return CodeBlock.of("return $T.<$T>forFactoryMethod($T.class, $S)",
BeanInstanceSupplier.class, beanClass, declaringClass,
factoryMethodName);
}
CodeBlock parameterTypes = generateParameterTypesCode(
factoryMethod.getParameterTypes(), 0);
return CodeBlock.of("return $T.forFactoryMethod($T.class, $S, $L)",
BeanInstanceSupplier.class, declaringClass,
return CodeBlock.of("return $T.<$T>forFactoryMethod($T.class, $S, $L)",
BeanInstanceSupplier.class, beanClass, declaringClass,
factoryMethodName, parameterTypes);
}

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

@ -158,6 +158,45 @@ class BeanDefinitionMethodGeneratorTests { @@ -158,6 +158,45 @@ class BeanDefinitionMethodGeneratorTests {
});
}
@Test // gh-28748
void generateBeanDefinitionMethodWhenHasInstancePostProcessorAndFactoryMethodGeneratesMethod() {
this.beanFactory.registerBeanDefinition("testBeanConfiguration", new RootBeanDefinition(TestBeanConfiguration.class));
RootBeanDefinition beanDefinition = new RootBeanDefinition(TestBean.class);
beanDefinition.setFactoryBeanName("testBeanConfiguration");
beanDefinition.setFactoryMethodName("testBean");
RegisteredBean registeredBean = registerBean(beanDefinition);
BeanRegistrationAotContribution aotContribution = (generationContext,
beanRegistrationCode) -> {
GeneratedMethod generatedMethod = beanRegistrationCode.getMethods().add("postProcess", method ->
method.addModifiers(Modifier.STATIC)
.addParameter(RegisteredBean.class, "registeredBean")
.addParameter(TestBean.class, "testBean")
.returns(TestBean.class).addCode("return new $T($S);", TestBean.class, "postprocessed"));
beanRegistrationCode.addInstancePostProcessor(MethodReference.ofStatic(
beanRegistrationCode.getClassName(), generatedMethod.getName()));
};
List<BeanRegistrationAotContribution> aotContributions = Collections
.singletonList(aotContribution);
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
this.methodGeneratorFactory, registeredBean, null, aotContributions);
MethodReference method = generator.generateBeanDefinitionMethod(
this.generationContext, this.beanRegistrationsCode);
compile(method, (actual, compiled) -> {
assertThat(compiled.getSourceFile(".*BeanDefinitions")).contains("BeanInstanceSupplier");
assertThat(actual.getBeanClass()).isEqualTo(TestBean.class);
InstanceSupplier<?> supplier = (InstanceSupplier<?>) actual
.getInstanceSupplier();
try {
TestBean instance = (TestBean) supplier.get(registeredBean);
assertThat(instance.getName()).isEqualTo("postprocessed");
}
catch (Exception ex) {
}
SourceFile sourceFile = compiled.getSourceFile(".*BeanDefinitions");
assertThat(sourceFile).contains("instanceSupplier.andThen(");
});
}
@Test
void generateBeanDefinitionMethodWhenHasCodeFragmentsCustomizerGeneratesMethod() {
RegisteredBean registeredBean = registerBean(
@ -373,7 +412,7 @@ class BeanDefinitionMethodGeneratorTests { @@ -373,7 +412,7 @@ class BeanDefinitionMethodGeneratorTests {
.addCode("return $L;", method.toInvokeCodeBlock()).build());
});
this.generationContext.writeGeneratedContent();
TestCompiler.forSystem().withFiles(this.generatedFiles).compile(compiled ->
TestCompiler.forSystem().withFiles(this.generatedFiles).printFiles(System.out).compile(compiled ->
result.accept((RootBeanDefinition) compiled.getInstance(Supplier.class).get(), compiled));
}

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

@ -94,7 +94,7 @@ class BeanInstanceSupplierTests { @@ -94,7 +94,7 @@ class BeanInstanceSupplierTests {
@Test
void forConstructorWhenNotFoundThrowsException() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<InputStream> resolver = BeanInstanceSupplier
.forConstructor(InputStream.class);
Source source = new Source(SingleArgConstructor.class, resolver);
RegisteredBean registerBean = source.registerBean(this.beanFactory);
@ -106,7 +106,7 @@ class BeanInstanceSupplierTests { @@ -106,7 +106,7 @@ class BeanInstanceSupplierTests {
@Test
void forConstructorReturnsNullFactoryMethod() {
BeanInstanceSupplier resolver = BeanInstanceSupplier.forConstructor(String.class);
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier.forConstructor(String.class);
assertThat(resolver.getFactoryMethod()).isNull();
}
@ -146,7 +146,7 @@ class BeanInstanceSupplierTests { @@ -146,7 +146,7 @@ class BeanInstanceSupplierTests {
@Test
void forFactoryMethodWhenNotFoundThrowsException() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<InputStream> resolver = BeanInstanceSupplier
.forFactoryMethod(SingleArgFactory.class, "single", InputStream.class);
Source source = new Source(String.class, resolver);
RegisteredBean registerBean = source.registerBean(this.beanFactory);
@ -158,7 +158,7 @@ class BeanInstanceSupplierTests { @@ -158,7 +158,7 @@ class BeanInstanceSupplierTests {
@Test
void forFactoryMethodReturnsFactoryMethod() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<String> resolver = BeanInstanceSupplier
.forFactoryMethod(SingleArgFactory.class, "single", String.class);
Method factoryMethod = ReflectionUtils.findMethod(SingleArgFactory.class, "single", String.class);
assertThat(factoryMethod).isNotNull();
@ -167,7 +167,7 @@ class BeanInstanceSupplierTests { @@ -167,7 +167,7 @@ class BeanInstanceSupplierTests {
@Test
void withGeneratorWhenBiFunctionIsNullThrowsException() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
.forConstructor();
assertThatIllegalArgumentException()
.isThrownBy(() -> resolver.withGenerator(
@ -177,7 +177,7 @@ class BeanInstanceSupplierTests { @@ -177,7 +177,7 @@ class BeanInstanceSupplierTests {
@Test
void withGeneratorWhenFunctionIsNullThrowsException() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
.forConstructor();
assertThatIllegalArgumentException()
.isThrownBy(() -> resolver.withGenerator(
@ -187,7 +187,7 @@ class BeanInstanceSupplierTests { @@ -187,7 +187,7 @@ class BeanInstanceSupplierTests {
@Test
void withGeneratorWhenSupplierIsNullThrowsException() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
.forConstructor();
assertThatIllegalArgumentException()
.isThrownBy(() -> resolver.withGenerator(
@ -197,7 +197,7 @@ class BeanInstanceSupplierTests { @@ -197,7 +197,7 @@ class BeanInstanceSupplierTests {
@Test
void getWithConstructorDoesNotSetResolvedFactoryMethod() throws Exception {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<SingleArgConstructor> resolver = BeanInstanceSupplier
.forConstructor(String.class);
this.beanFactory.registerSingleton("one", "1");
Source source = new Source(SingleArgConstructor.class, resolver);
@ -211,7 +211,7 @@ class BeanInstanceSupplierTests { @@ -211,7 +211,7 @@ class BeanInstanceSupplierTests {
void getWithFactoryMethodSetsResolvedFactoryMethod() {
Method factoryMethod = ReflectionUtils.findMethod(SingleArgFactory.class, "single", String.class);
assertThat(factoryMethod).isNotNull();
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<String> resolver = BeanInstanceSupplier
.forFactoryMethod(SingleArgFactory.class, "single", String.class);
RootBeanDefinition beanDefinition = new RootBeanDefinition(String.class);
assertThat(beanDefinition.getResolvedFactoryMethod()).isNull();
@ -225,7 +225,7 @@ class BeanInstanceSupplierTests { @@ -225,7 +225,7 @@ class BeanInstanceSupplierTests {
this.beanFactory.registerSingleton("one", "1");
RegisteredBean registerBean = registrar.registerBean(this.beanFactory);
List<Object> result = new ArrayList<>();
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
.forConstructor(String.class)
.withGenerator((registeredBean, args) -> result.add(args));
resolver.get(registerBean);
@ -238,8 +238,8 @@ class BeanInstanceSupplierTests { @@ -238,8 +238,8 @@ class BeanInstanceSupplierTests {
BeanRegistrar registrar = new BeanRegistrar(SingleArgConstructor.class);
this.beanFactory.registerSingleton("one", "1");
RegisteredBean registerBean = registrar.registerBean(this.beanFactory);
BeanInstanceSupplier resolver = BeanInstanceSupplier
.forConstructor(String.class)
BeanInstanceSupplier<String> resolver = BeanInstanceSupplier
.<String>forConstructor(String.class)
.withGenerator(registeredBean -> "1");
assertThat(resolver.get(registerBean)).isInstanceOf(String.class).isEqualTo("1");
}
@ -249,15 +249,15 @@ class BeanInstanceSupplierTests { @@ -249,15 +249,15 @@ class BeanInstanceSupplierTests {
BeanRegistrar registrar = new BeanRegistrar(SingleArgConstructor.class);
this.beanFactory.registerSingleton("one", "1");
RegisteredBean registerBean = registrar.registerBean(this.beanFactory);
BeanInstanceSupplier resolver = BeanInstanceSupplier
.forConstructor(String.class)
BeanInstanceSupplier<String> resolver = BeanInstanceSupplier
.<String>forConstructor(String.class)
.withGenerator(() -> "1");
assertThat(resolver.get(registerBean)).isInstanceOf(String.class).isEqualTo("1");
}
@Test
void getWhenRegisteredBeanIsNullThrowsException() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
.forConstructor(String.class);
assertThatIllegalArgumentException().isThrownBy(() -> resolver.get((RegisteredBean) null))
.withMessage("'registeredBean' must not be null");
@ -548,7 +548,7 @@ class BeanInstanceSupplierTests { @@ -548,7 +548,7 @@ class BeanInstanceSupplierTests {
}
};
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
.forConstructor(String.class);
Source source = new Source(String.class, resolver);
beanFactory.registerSingleton("one", "1");
@ -561,7 +561,7 @@ class BeanInstanceSupplierTests { @@ -561,7 +561,7 @@ class BeanInstanceSupplierTests {
@Test
void resolveArgumentsRegistersDependantBeans() {
BeanInstanceSupplier resolver = BeanInstanceSupplier
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
.forConstructor(String.class);
Source source = new Source(SingleArgConstructor.class, resolver);
this.beanFactory.registerSingleton("one", "1");
@ -724,7 +724,7 @@ class BeanInstanceSupplierTests { @@ -724,7 +724,7 @@ class BeanInstanceSupplierTests {
protected abstract void setup();
protected final void add(Class<?> beanClass,
BeanInstanceSupplier resolver) {
BeanInstanceSupplier<?> resolver) {
this.arguments.add(Arguments.of(new Source(beanClass, resolver)));
}
@ -762,15 +762,15 @@ class BeanInstanceSupplierTests { @@ -762,15 +762,15 @@ class BeanInstanceSupplierTests {
static class Source extends BeanRegistrar {
private final BeanInstanceSupplier resolver;
private final BeanInstanceSupplier<?> resolver;
public Source(Class<?> beanClass,
BeanInstanceSupplier resolver) {
BeanInstanceSupplier<?> resolver) {
super(beanClass);
this.resolver = resolver;
}
BeanInstanceSupplier getResolver() {
BeanInstanceSupplier<?> getResolver() {
return this.resolver;
}

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

@ -172,7 +172,7 @@ class InstanceSupplierCodeGeneratorTests { @@ -172,7 +172,7 @@ class InstanceSupplierCodeGeneratorTests {
instanceSupplier);
assertThat(bean).isInstanceOf(TestBeanWithPrivateConstructor.class);
assertThat(compiled.getSourceFile())
.contains("return BeanInstanceSupplier.forConstructor();");
.contains("return BeanInstanceSupplier.<TestBeanWithPrivateConstructor>forConstructor();");
});
assertThat(getReflectionHints().getTypeHint(TestBeanWithPrivateConstructor.class))
.satisfies(hasConstructorWithMode(ExecutableMode.INVOKE));
@ -211,7 +211,7 @@ class InstanceSupplierCodeGeneratorTests { @@ -211,7 +211,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(bean).isInstanceOf(String.class);
assertThat(bean).isEqualTo("Hello");
assertThat(compiled.getSourceFile())
.contains("BeanInstanceSupplier.forFactoryMethod")
.contains("forFactoryMethod")
.doesNotContain("withGenerator");
});
assertThat(getReflectionHints().getTypeHint(SimpleConfiguration.class))
@ -325,7 +325,7 @@ class InstanceSupplierCodeGeneratorTests { @@ -325,7 +325,7 @@ class InstanceSupplierCodeGeneratorTests {
.addStatement("return $L", generatedCode).build());
});
this.generationContext.writeGeneratedContent();
TestCompiler.forSystem().withFiles(this.generatedFiles).compile(compiled ->
TestCompiler.forSystem().withFiles(this.generatedFiles).printFiles(System.out).compile(compiled ->
result.accept((InstanceSupplier<?>) compiled.getInstance(Supplier.class).get(), compiled));
}

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

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.aot;
import org.springframework.beans.testfixture.beans.TestBean;
/**
* Test {@code @Configuration} style class to create {@link TestBean}.
*
* @author Phillip Webb
*/
public class TestBeanConfiguration {
public TestBean testBean() {
return new TestBean();
}
}
Loading…
Cancel
Save