Browse Source

Add first class ParameterizedTypeReference support to BeanRegistrar

This commit replaces ParameterizedTypeReference and ResolvableType
target type customization with the lambda by directly exposing
ParameterizedTypeReference methods at top level, as generics
variants of the class-based existing ones.

Closes gh-35635
pull/35649/head
Sébastien Deleuze 2 months ago
parent
commit
b46c41bb3a
  1. 106
      spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java
  2. 84
      spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java
  3. 26
      spring-beans/src/main/kotlin/org/springframework/beans/factory/BeanRegistrarDsl.kt
  4. 25
      spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java
  5. 5
      spring-context/src/testFixtures/java/org/springframework/context/testfixture/beans/factory/GenericBeanRegistrar.java

106
spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java

@ -24,7 +24,6 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -55,43 +54,92 @@ public interface BeanRegistry {
void registerAlias(String name, String alias); void registerAlias(String name, String alias);
/** /**
* Register a bean from the given bean class, which will be instantiated using the * Register a bean from the given class, which will be instantiated using the
* related {@link BeanUtils#getResolvableConstructor resolvable constructor} if any. * related {@link BeanUtils#getResolvableConstructor resolvable constructor} if any.
* <p>For registering a bean with a generic type, consider
* {@link #registerBean(ParameterizedTypeReference)}.
* @param beanClass the class of the bean * @param beanClass the class of the bean
* @return the generated bean name * @return the generated bean name
* @see #registerBean(Class)
*/ */
<T> String registerBean(Class<T> beanClass); <T> String registerBean(Class<T> beanClass);
/** /**
* Register a bean from the given bean class, customizing it with the customizer * Register a bean from the given generics-containing type, which will be
* instantiated using the related
* {@link BeanUtils#getResolvableConstructor resolvable constructor} if any.
* @param beanType the generics-containing type of the bean
* @return the generated bean name
*/
<T> String registerBean(ParameterizedTypeReference<T> beanType);
/**
* Register a bean from the given class, customizing it with the customizer
* callback. The bean will be instantiated using the supplier that can be configured * callback. The bean will be instantiated using the supplier that can be configured
* in the customizer callback, or will be tentatively instantiated with its * in the customizer callback, or will be tentatively instantiated with its
* {@link BeanUtils#getResolvableConstructor resolvable constructor} otherwise. * {@link BeanUtils#getResolvableConstructor resolvable constructor} otherwise.
* <p>For registering a bean with a generic type, consider
* {@link #registerBean(ParameterizedTypeReference, Consumer)}.
* @param beanClass the class of the bean * @param beanClass the class of the bean
* @param customizer callback to customize other bean properties than the name * @param customizer the callback to customize other bean properties than the name
* @return the generated bean name * @return the generated bean name
*/ */
<T> String registerBean(Class<T> beanClass, Consumer<Spec<T>> customizer); <T> String registerBean(Class<T> beanClass, Consumer<Spec<T>> customizer);
/** /**
* Register a bean from the given bean class, which will be instantiated using the * Register a bean from the given generics-containing type, customizing it
* with the customizer callback. The bean will be instantiated using the supplier
* that can be configured in the customizer callback, or will be tentatively instantiated
* with its {@link BeanUtils#getResolvableConstructor resolvable constructor} otherwise.
* @param beanType the generics-containing type of the bean
* @param customizer the callback to customize other bean properties than the name
* @return the generated bean name
*/
<T> String registerBean(ParameterizedTypeReference<T> beanType, Consumer<Spec<T>> customizer);
/**
* Register a bean from the given class, which will be instantiated using the
* related {@link BeanUtils#getResolvableConstructor resolvable constructor} if any. * related {@link BeanUtils#getResolvableConstructor resolvable constructor} if any.
* <p>For registering a bean with a generic type, consider
* {@link #registerBean(String, ParameterizedTypeReference)}.
* @param name the name of the bean * @param name the name of the bean
* @param beanClass the class of the bean * @param beanClass the class of the bean
*/ */
<T> void registerBean(String name, Class<T> beanClass); <T> void registerBean(String name, Class<T> beanClass);
/** /**
* Register a bean from the given bean class, customizing it with the customizer * Register a bean from the given generics-containing type, which
* will be instantiated using the related
* {@link BeanUtils#getResolvableConstructor resolvable constructor} if any.
* @param name the name of the bean
* @param beanType the generics-containing type of the bean
*/
<T> void registerBean(String name, ParameterizedTypeReference<T> beanType);
/**
* Register a bean from the given class, customizing it with the customizer
* callback. The bean will be instantiated using the supplier that can be configured * callback. The bean will be instantiated using the supplier that can be configured
* in the customizer callback, or will be tentatively instantiated with its * in the customizer callback, or will be tentatively instantiated with its
* {@link BeanUtils#getResolvableConstructor resolvable constructor} otherwise. * {@link BeanUtils#getResolvableConstructor resolvable constructor} otherwise.
* <p>For registering a bean with a generic type, consider
* {@link #registerBean(String, ParameterizedTypeReference, Consumer)}.
* @param name the name of the bean * @param name the name of the bean
* @param beanClass the class of the bean * @param beanClass the class of the bean
* @param customizer callback to customize other bean properties than the name * @param customizer the callback to customize other bean properties than the name
*/ */
<T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>> customizer); <T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>> customizer);
/**
* Register a bean from the given generics-containing type, customizing it
* with the customizer callback. The bean will be instantiated using the supplier
* that can be configured in the customizer callback, or will be tentatively instantiated
* with its {@link BeanUtils#getResolvableConstructor resolvable constructor} otherwise.
* @param name the name of the bean
* @param beanType the generics-containing type of the bean
* @param customizer the callback to customize other bean properties than the name
*/
<T> void registerBean(String name, ParameterizedTypeReference<T> beanType, Consumer<Spec<T>> customizer);
/** /**
* Specification for customizing a bean. * Specification for customizing a bean.
@ -164,20 +212,6 @@ public interface BeanRegistry {
* @see AbstractBeanDefinition#setInstanceSupplier(Supplier) * @see AbstractBeanDefinition#setInstanceSupplier(Supplier)
*/ */
Spec<T> supplier(Function<SupplierContext, T> supplier); Spec<T> supplier(Function<SupplierContext, T> supplier);
/**
* Set a generics-containing target type of this bean.
* @see #targetType(ResolvableType)
* @see RootBeanDefinition#setTargetType(ResolvableType)
*/
Spec<T> targetType(ParameterizedTypeReference<? extends T> type);
/**
* Set a generics-containing target type of this bean.
* @see #targetType(ParameterizedTypeReference)
* @see RootBeanDefinition#setTargetType(ResolvableType)
*/
Spec<T> targetType(ResolvableType type);
} }
@ -188,32 +222,40 @@ public interface BeanRegistry {
interface SupplierContext { interface SupplierContext {
/** /**
* Return the bean instance that uniquely matches the given object type, if any. * Return the bean instance that uniquely matches the given type, if any.
* @param requiredType type the bean must match; can be an interface or superclass * @param beanClass the type the bean must match; can be an interface or superclass
* @return an instance of the single bean matching the required type * @return an instance of the single bean matching the bean type
* @see BeanFactory#getBean(String)
*/
<T> T bean(Class<T> beanClass) throws BeansException;
/**
* Return the bean instance that uniquely matches the given generics-containing type, if any.
* @param beanType the generics-containing type the bean must match; can be an interface or superclass
* @return an instance of the single bean matching the bean type
* @see BeanFactory#getBean(String) * @see BeanFactory#getBean(String)
*/ */
<T> T bean(Class<T> requiredType) throws BeansException; <T> T bean(ParameterizedTypeReference<T> beanType) throws BeansException;
/** /**
* Return an instance, which may be shared or independent, of the * Return an instance, which may be shared or independent, of the
* specified bean. * specified bean.
* @param name the name of the bean to retrieve * @param name the name of the bean to retrieve
* @param requiredType type the bean must match; can be an interface or superclass * @param beanClass the type the bean must match; can be an interface or superclass
* @return an instance of the bean. * @return an instance of the bean.
* @see BeanFactory#getBean(String, Class) * @see BeanFactory#getBean(String, Class)
*/ */
<T> T bean(String name, Class<T> requiredType) throws BeansException; <T> T bean(String name, Class<T> beanClass) throws BeansException;
/** /**
* Return a provider for the specified bean, allowing for lazy on-demand retrieval * Return a provider for the specified bean, allowing for lazy on-demand retrieval
* of instances, including availability and uniqueness options. * of instances, including availability and uniqueness options.
* <p>For matching a generic type, consider {@link #beanProvider(ResolvableType)}. * <p>For matching a generic type, consider {@link #beanProvider(ParameterizedTypeReference)}.
* @param requiredType type the bean must match; can be an interface or superclass * @param beanClass the type the bean must match; can be an interface or superclass
* @return a corresponding provider handle * @return a corresponding provider handle
* @see BeanFactory#getBeanProvider(Class) * @see BeanFactory#getBeanProvider(Class)
*/ */
<T> ObjectProvider<T> beanProvider(Class<T> requiredType); <T> ObjectProvider<T> beanProvider(Class<T> beanClass);
/** /**
* Return a provider for the specified bean, allowing for lazy on-demand retrieval * Return a provider for the specified bean, allowing for lazy on-demand retrieval
@ -229,11 +271,11 @@ public interface BeanRegistry {
* Java compiler warning), consider calling {@link #beanProvider(Class)} with the * Java compiler warning), consider calling {@link #beanProvider(Class)} with the
* raw type as a second step if no full generic match is * raw type as a second step if no full generic match is
* {@link ObjectProvider#getIfAvailable() available} with this variant. * {@link ObjectProvider#getIfAvailable() available} with this variant.
* @param requiredType type the bean must match; can be a generic type declaration * @param beanType the generics-containing type the bean must match; can be an interface or superclass
* @return a corresponding provider handle * @return a corresponding provider handle
* @see BeanFactory#getBeanProvider(ResolvableType) * @see BeanFactory#getBeanProvider(ResolvableType)
*/ */
<T> ObjectProvider<T> beanProvider(ResolvableType requiredType); <T> ObjectProvider<T> beanProvider(ParameterizedTypeReference<T> beanType);
} }
} }

84
spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java

@ -17,6 +17,7 @@
package org.springframework.beans.factory.support; package org.springframework.beans.factory.support;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
@ -92,6 +93,14 @@ public class BeanRegistryAdapter implements BeanRegistry {
return beanName; return beanName;
} }
@Override
public <T> String registerBean(ParameterizedTypeReference<T> beanType) {
ResolvableType resolvableType = ResolvableType.forType(beanType);
String beanName = BeanDefinitionReaderUtils.uniqueBeanName(Objects.requireNonNull(resolvableType.resolve()).getName(), this.beanRegistry);
registerBean(beanName, beanType);
return beanName;
}
@Override @Override
public <T> String registerBean(Class<T> beanClass, Consumer<Spec<T>> customizer) { public <T> String registerBean(Class<T> beanClass, Consumer<Spec<T>> customizer) {
String beanName = BeanDefinitionReaderUtils.uniqueBeanName(beanClass.getName(), this.beanRegistry); String beanName = BeanDefinitionReaderUtils.uniqueBeanName(beanClass.getName(), this.beanRegistry);
@ -99,6 +108,15 @@ public class BeanRegistryAdapter implements BeanRegistry {
return beanName; return beanName;
} }
@Override
public <T> String registerBean(ParameterizedTypeReference<T> beanType, Consumer<Spec<T>> customizer) {
ResolvableType resolvableType = ResolvableType.forType(beanType);
Class<?> beanClass = Objects.requireNonNull(resolvableType.resolve());
String beanName = BeanDefinitionReaderUtils.uniqueBeanName(beanClass.getName(), this.beanRegistry);
registerBean(beanName, beanType, customizer);
return beanName;
}
@Override @Override
public <T> void registerBean(String name, Class<T> beanClass) { public <T> void registerBean(String name, Class<T> beanClass) {
BeanRegistrarBeanDefinition beanDefinition = new BeanRegistrarBeanDefinition(beanClass, this.beanRegistrarClass); BeanRegistrarBeanDefinition beanDefinition = new BeanRegistrarBeanDefinition(beanClass, this.beanRegistrarClass);
@ -111,9 +129,11 @@ public class BeanRegistryAdapter implements BeanRegistry {
} }
@Override @Override
public <T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>> spec) { public <T> void registerBean(String name, ParameterizedTypeReference<T> beanType) {
ResolvableType resolvableType = ResolvableType.forType(beanType);
Class<?> beanClass = Objects.requireNonNull(resolvableType.resolve());
BeanRegistrarBeanDefinition beanDefinition = new BeanRegistrarBeanDefinition(beanClass, this.beanRegistrarClass); BeanRegistrarBeanDefinition beanDefinition = new BeanRegistrarBeanDefinition(beanClass, this.beanRegistrarClass);
spec.accept(new BeanSpecAdapter<>(beanDefinition, this.beanFactory)); beanDefinition.setTargetType(resolvableType);
if (this.customizers != null && this.customizers.containsKey(name)) { if (this.customizers != null && this.customizers.containsKey(name)) {
for (BeanDefinitionCustomizer customizer : this.customizers.get(name)) { for (BeanDefinitionCustomizer customizer : this.customizers.get(name)) {
customizer.customize(beanDefinition); customizer.customize(beanDefinition);
@ -122,6 +142,33 @@ public class BeanRegistryAdapter implements BeanRegistry {
this.beanRegistry.registerBeanDefinition(name, beanDefinition); this.beanRegistry.registerBeanDefinition(name, beanDefinition);
} }
@Override
public <T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>> customizer) {
BeanRegistrarBeanDefinition beanDefinition = new BeanRegistrarBeanDefinition(beanClass, this.beanRegistrarClass);
customizer.accept(new BeanSpecAdapter<>(beanDefinition, this.beanFactory));
if (this.customizers != null && this.customizers.containsKey(name)) {
for (BeanDefinitionCustomizer registryCustomizer : this.customizers.get(name)) {
registryCustomizer.customize(beanDefinition);
}
}
this.beanRegistry.registerBeanDefinition(name, beanDefinition);
}
@Override
public <T> void registerBean(String name, ParameterizedTypeReference<T> beanType, Consumer<Spec<T>> customizer) {
ResolvableType resolvableType = ResolvableType.forType(beanType);
Class<?> beanClass = Objects.requireNonNull(resolvableType.resolve());
BeanRegistrarBeanDefinition beanDefinition = new BeanRegistrarBeanDefinition(beanClass, this.beanRegistrarClass);
beanDefinition.setTargetType(resolvableType);
customizer.accept(new BeanSpecAdapter<>(beanDefinition, this.beanFactory));
if (this.customizers != null && this.customizers.containsKey(name)) {
for (BeanDefinitionCustomizer registryCustomizer : this.customizers.get(name)) {
registryCustomizer.customize(beanDefinition);
}
}
this.beanRegistry.registerBeanDefinition(name, beanDefinition);
}
@Override @Override
public void register(BeanRegistrar registrar) { public void register(BeanRegistrar registrar) {
Assert.notNull(registrar, "'registrar' must not be null"); Assert.notNull(registrar, "'registrar' must not be null");
@ -238,18 +285,6 @@ public class BeanRegistryAdapter implements BeanRegistry {
supplier.apply(new SupplierContextAdapter(this.beanFactory))); supplier.apply(new SupplierContextAdapter(this.beanFactory)));
return this; return this;
} }
@Override
public Spec<T> targetType(ParameterizedTypeReference<? extends T> targetType) {
this.beanDefinition.setTargetType(ResolvableType.forType(targetType));
return this;
}
@Override
public Spec<T> targetType(ResolvableType targetType) {
this.beanDefinition.setTargetType(targetType);
return this;
}
} }
@ -262,23 +297,28 @@ public class BeanRegistryAdapter implements BeanRegistry {
} }
@Override @Override
public <T> T bean(Class<T> requiredType) throws BeansException { public <T> T bean(Class<T> beanClass) throws BeansException {
return this.beanFactory.getBean(requiredType); return this.beanFactory.getBean(beanClass);
}
@Override
public <T> T bean(ParameterizedTypeReference<T> beanType) throws BeansException {
return this.beanFactory.getBeanProvider(beanType).getObject();
} }
@Override @Override
public <T> T bean(String name, Class<T> requiredType) throws BeansException { public <T> T bean(String name, Class<T> beanClass) throws BeansException {
return this.beanFactory.getBean(name, requiredType); return this.beanFactory.getBean(name, beanClass);
} }
@Override @Override
public <T> ObjectProvider<T> beanProvider(Class<T> requiredType) { public <T> ObjectProvider<T> beanProvider(Class<T> beanClass) {
return this.beanFactory.getBeanProvider(requiredType); return this.beanFactory.getBeanProvider(beanClass);
} }
@Override @Override
public <T> ObjectProvider<T> beanProvider(ResolvableType requiredType) { public <T> ObjectProvider<T> beanProvider(ParameterizedTypeReference<T> beanType) {
return this.beanFactory.getBeanProvider(requiredType); return this.beanFactory.getBeanProvider(beanType);
} }
} }

26
spring-beans/src/main/kotlin/org/springframework/beans/factory/BeanRegistrarDsl.kt

@ -168,12 +168,8 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
if (prototype) { if (prototype) {
it.prototype() it.prototype()
} }
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
if (resolvableType.hasGenerics()) {
it.targetType(resolvableType)
}
} }
registry.registerBean(name, T::class.java, customizer) registry.registerBean(name, object: ParameterizedTypeReference<T>() {}, customizer)
} }
/** /**
@ -234,12 +230,8 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
if (prototype) { if (prototype) {
it.prototype() it.prototype()
} }
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
if (resolvableType.hasGenerics()) {
it.targetType(resolvableType)
}
} }
return registry.registerBean(T::class.java, customizer) return registry.registerBean(object: ParameterizedTypeReference<T>() {}, customizer)
} }
/** /**
@ -304,12 +296,8 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
it.supplier { it.supplier {
SupplierContextDsl<T>(it, env).supplier() SupplierContextDsl<T>(it, env).supplier()
} }
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
if (resolvableType.hasGenerics()) {
it.targetType(resolvableType)
}
} }
registry.registerBean(name, T::class.java, customizer) registry.registerBean(name, object: ParameterizedTypeReference<T>() {}, customizer)
} }
inline fun <reified T : Any> registerBean(autowirable: Boolean = true, inline fun <reified T : Any> registerBean(autowirable: Boolean = true,
@ -372,12 +360,8 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
it.supplier { it.supplier {
SupplierContextDsl<T>(it, env).supplier() SupplierContextDsl<T>(it, env).supplier()
} }
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
if (resolvableType.hasGenerics()) {
it.targetType(resolvableType)
}
} }
return registry.registerBean(T::class.java, customizer) return registry.registerBean(object: ParameterizedTypeReference<T>() {}, customizer)
} }
// Function with 0 parameter // Function with 0 parameter
@ -1094,7 +1078,7 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
* @return a corresponding provider handle * @return a corresponding provider handle
*/ */
inline fun <reified T : Any> beanProvider() : ObjectProvider<T> = inline fun <reified T : Any> beanProvider() : ObjectProvider<T> =
context.beanProvider(ResolvableType.forType((object : ParameterizedTypeReference<T>() {}).type)) context.beanProvider(object : ParameterizedTypeReference<T>() {})
} }
override fun register(registry: BeanRegistry, env: Environment) { override fun register(registry: BeanRegistry, env: Environment) {

25
spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java

@ -24,7 +24,6 @@ import org.springframework.beans.factory.BeanRegistrar;
import org.springframework.beans.factory.BeanRegistry; import org.springframework.beans.factory.BeanRegistry;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment; import org.springframework.core.env.StandardEnvironment;
@ -206,18 +205,10 @@ public class BeanRegistryAdapterTests {
} }
@Test @Test
void customTargetTypeFromResolvableType() { void genericType() {
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, env, TargetTypeBeanRegistrar.class); BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, env, GenericTypeBeanRegistrar.class);
new TargetTypeBeanRegistrar().register(adapter, env); new GenericTypeBeanRegistrar().register(adapter, env);
RootBeanDefinition beanDefinition = (RootBeanDefinition)this.beanFactory.getBeanDefinition("fooSupplierFromResolvableType"); RootBeanDefinition beanDefinition = (RootBeanDefinition)this.beanFactory.getBeanDefinition("fooSupplier");
assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(Foo.class);
}
@Test
void customTargetTypeFromTypeReference() {
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, env, TargetTypeBeanRegistrar.class);
new TargetTypeBeanRegistrar().register(adapter, env);
RootBeanDefinition beanDefinition = (RootBeanDefinition)this.beanFactory.getBeanDefinition("fooSupplierFromTypeReference");
assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(Foo.class); assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(Foo.class);
} }
@ -325,15 +316,11 @@ public class BeanRegistryAdapterTests {
} }
} }
private static class TargetTypeBeanRegistrar implements BeanRegistrar { private static class GenericTypeBeanRegistrar implements BeanRegistrar {
@Override @Override
public void register(BeanRegistry registry, Environment env) { public void register(BeanRegistry registry, Environment env) {
registry.registerBean("fooSupplierFromResolvableType", Foo.class, registry.registerBean("fooSupplier", new ParameterizedTypeReference<Supplier<Foo>>() {});
spec -> spec.targetType(ResolvableType.forClassWithGenerics(Supplier.class, Foo.class)));
ParameterizedTypeReference<Supplier<Foo>> type = new ParameterizedTypeReference<>() {};
registry.registerBean("fooSupplierFromTypeReference", Supplier.class,
spec -> spec.targetType(type));
} }
} }

5
spring-context/src/testFixtures/java/org/springframework/context/testfixture/beans/factory/GenericBeanRegistrar.java

@ -27,9 +27,8 @@ public class GenericBeanRegistrar implements BeanRegistrar {
@Override @Override
public void register(BeanRegistry registry, Environment env) { public void register(BeanRegistry registry, Environment env) {
ParameterizedTypeReference<Supplier<Foo>> type = new ParameterizedTypeReference<>() {}; registry.registerBean("fooSupplier", new ParameterizedTypeReference<Supplier<Foo>>() {}, spec ->
registry.registerBean("fooSupplier", Supplier.class, spec -> spec.targetType(type) spec.supplier(context-> (Supplier<Foo>) Foo::new));
.supplier(context-> (Supplier<Foo>) Foo::new));
} }
public record Foo() {} public record Foo() {}

Loading…
Cancel
Save