Add generics to BeanInstanceSupplier
Update `BeanInstanceSupplier` to support a generic type. See gh-28748
This commit is contained in:
@@ -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
|
||||
/**
|
||||
* 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
|
||||
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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
.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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@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 {
|
||||
|
||||
@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 {
|
||||
|
||||
@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 {
|
||||
|
||||
@Test
|
||||
void withGeneratorWhenBiFunctionIsNullThrowsException() {
|
||||
BeanInstanceSupplier resolver = BeanInstanceSupplier
|
||||
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
|
||||
.forConstructor();
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> resolver.withGenerator(
|
||||
@@ -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 {
|
||||
|
||||
@Test
|
||||
void withGeneratorWhenSupplierIsNullThrowsException() {
|
||||
BeanInstanceSupplier resolver = BeanInstanceSupplier
|
||||
BeanInstanceSupplier<Object> resolver = BeanInstanceSupplier
|
||||
.forConstructor();
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> resolver.withGenerator(
|
||||
@@ -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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
}
|
||||
|
||||
};
|
||||
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 {
|
||||
|
||||
@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 {
|
||||
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 {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
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 {
|
||||
.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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user