Add support for target type to BeanRegistry
Closes gh-34560
This commit is contained in:
@@ -24,6 +24,8 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@@ -149,6 +151,20 @@ public interface BeanRegistry {
|
||||
* @see AbstractBeanDefinition#setInstanceSupplier(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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
@@ -211,6 +212,18 @@ public class BeanRegistryAdapter implements BeanRegistry {
|
||||
supplier.apply(new SupplierContextAdapter(this.beanFactory)));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static class SupplierContextAdapter implements SupplierContext {
|
||||
|
||||
@@ -122,6 +122,10 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
|
||||
if (prototype) {
|
||||
it.prototype()
|
||||
}
|
||||
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
|
||||
if (resolvableType.hasGenerics()) {
|
||||
it.targetType(resolvableType)
|
||||
}
|
||||
}
|
||||
registry.registerBean(name, T::class.java, customizer)
|
||||
}
|
||||
@@ -184,6 +188,10 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
|
||||
if (prototype) {
|
||||
it.prototype()
|
||||
}
|
||||
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
|
||||
if (resolvableType.hasGenerics()) {
|
||||
it.targetType(resolvableType)
|
||||
}
|
||||
}
|
||||
return registry.registerBean(T::class.java, customizer)
|
||||
}
|
||||
@@ -250,6 +258,10 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
|
||||
it.supplier {
|
||||
SupplierContextDsl<T>(it).supplier()
|
||||
}
|
||||
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
|
||||
if (resolvableType.hasGenerics()) {
|
||||
it.targetType(resolvableType)
|
||||
}
|
||||
}
|
||||
registry.registerBean(name, T::class.java, customizer)
|
||||
}
|
||||
@@ -314,6 +326,10 @@ open class BeanRegistrarDsl(private val init: BeanRegistrarDsl.() -> Unit): Bean
|
||||
it.supplier {
|
||||
SupplierContextDsl<T>(it).supplier()
|
||||
}
|
||||
val resolvableType = ResolvableType.forType(object: ParameterizedTypeReference<T>() {});
|
||||
if (resolvableType.hasGenerics()) {
|
||||
it.targetType(resolvableType)
|
||||
}
|
||||
}
|
||||
return registry.registerBean(T::class.java, customizer)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.BeanRegistrar;
|
||||
import org.springframework.beans.factory.BeanRegistry;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
@@ -203,6 +205,22 @@ public class BeanRegistryAdapterTests {
|
||||
assertThat(supplier.get()).isNotNull().isInstanceOf(Foo.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTargetTypeFromResolvableType() {
|
||||
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, TargetTypeBeanRegistrar.class);
|
||||
new TargetTypeBeanRegistrar().register(adapter, env);
|
||||
RootBeanDefinition beanDefinition = (RootBeanDefinition)this.beanFactory.getBeanDefinition("fooSupplierFromResolvableType");
|
||||
assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(Foo.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTargetTypeFromTypeReference() {
|
||||
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, TargetTypeBeanRegistrar.class);
|
||||
new TargetTypeBeanRegistrar().register(adapter, env);
|
||||
RootBeanDefinition beanDefinition = (RootBeanDefinition)this.beanFactory.getBeanDefinition("fooSupplierFromTypeReference");
|
||||
assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(Foo.class);
|
||||
}
|
||||
|
||||
|
||||
private static class DefaultBeanRegistrar implements BeanRegistrar {
|
||||
|
||||
@@ -292,6 +310,18 @@ public class BeanRegistryAdapterTests {
|
||||
}
|
||||
}
|
||||
|
||||
private static class TargetTypeBeanRegistrar implements BeanRegistrar {
|
||||
|
||||
@Override
|
||||
public void register(BeanRegistry registry, Environment env) {
|
||||
registry.registerBean("fooSupplierFromResolvableType", Foo.class,
|
||||
spec -> spec.targetType(ResolvableType.forClassWithGenerics(Supplier.class, Foo.class)));
|
||||
ParameterizedTypeReference<Supplier<Foo>> type = new ParameterizedTypeReference<>() {};
|
||||
registry.registerBean("fooSupplierFromTypeReference", Supplier.class,
|
||||
spec -> spec.targetType(type));
|
||||
}
|
||||
}
|
||||
|
||||
private static class Foo {}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user