Spring 通用 bean 工厂
Spring generic bean factory
Spring 中是否有一种机制可以提供一种自动化构建通用 bean 的方法?
例如,如果我有一个 class 定义,例如:
class Foo<T> {
private final T type;
...
}
和依赖性如:
@Autowired
private Foo<String> foo;
我想在 Spring 中使用某种机制,以某种形式从依赖项定义(在上面的示例中为字符串)中提供 T 并提供一种自动创建实例的方法?
通过在您的 Spring 配置中定义它:
@Bean
public Foo<String> foo() {
return new Foo<>("bar");
}
或者您可以指定类型而不是值:
@Bean
public Foo<String> foo() {
return new Foo<>(String.class);
}
如果你使用Spring引导,你可以添加@ConditionalOnProperty
或@ConditionalOnBean
来动态化bean实例化。
(更新)如果你想避免声明,你应该扩展DefaultListableBeanFactory
和ApplicationContext
。这是 Spring Boot 的工作示例:
@Controller
@EnableAutoConfiguration
public class BeanFactoryTest {
public static void main(String[] args) throws Exception {
SpringApplication app = new SpringApplication(BeanFactoryTest.class);
app.setApplicationContextClass(CustomAppContext.class);
app.run(args);
}
@Autowired
private Foo<String> foo1;
@Autowired
private Foo<String> foo2;
@Autowired
private Foo<Integer> foo3;
@PostConstruct
public void initialize() {
System.out.println(foo1); // prints BeanFactoryTest$Foo@344b8190
System.out.println(foo2); // prints BeanFactoryTest$Foo@344b8190
System.out.println(foo3); // prints BeanFactoryTest$Foo@5b69d40d
}
public static class CustomAppContext extends AnnotationConfigApplicationContext {
public CustomAppContext() {
super(new CustomBeanFactory());
}
}
public static class CustomBeanFactory extends DefaultListableBeanFactory {
@Override
protected Map<String, Object> findAutowireCandidates(String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
Map<String, Object> map = super.findAutowireCandidates(beanName, requiredType, descriptor);
if (Foo.class.isAssignableFrom(requiredType)) {
ResolvableType type = ResolvableType.forField(descriptor.getField());
ResolvableType genericType = type.getGeneric(0);
Class<?> genericTypeRaw = genericType.getRawClass();
boolean hasInstance =
map.values()
.parallelStream()
.map(Foo.class::cast)
.map(Foo::getType)
.filter(genericTypeRaw::isAssignableFrom)
.findFirst()
.isPresent();
if (!hasInstance) {
super.registerResolvableDependency(requiredType, new Foo<>(genericTypeRaw));
map = super.findAutowireCandidates(beanName, requiredType, descriptor);
}
}
return map;
}
}
public static class Foo<T> {
private final Class<T> type;
public Foo(Class<T> type) {
this.type = type;
}
public Class<T> getType() {
return type;
}
}
}
看来你可以使用 Spring 中的 ResolvableType 4. http://docs.spring.io/spring/docs/4.0.0.RC2/javadoc-api/org/springframework/core/ResolvableType.html There is also a detail sample https://spring.io/blog/2013/12/03/spring-framework-4-0-and-java-generics
希望对您有所帮助。
这个问题有点老,但没有包含示例的答案,所以...
使用 ResolvableType:
public <E> Foo<E> produceFoo(final InjectionPoint ip) {
ResolvableType resolved = ResolvableType.forField(ip.getField());
Foo<E> fooInstance = new FooImpl<>();
Class<E> parameterClass = (Class<E>) resolved.getGeneric(0).resolve();
fooInstance.doSomethingWithParametrized(parameterClass);
return fooInstance;
}
InjectionPoint cames from: import org.springframework.beans.factory.InjectionPoint;
Spring 中是否有一种机制可以提供一种自动化构建通用 bean 的方法?
例如,如果我有一个 class 定义,例如:
class Foo<T> {
private final T type;
...
}
和依赖性如:
@Autowired
private Foo<String> foo;
我想在 Spring 中使用某种机制,以某种形式从依赖项定义(在上面的示例中为字符串)中提供 T 并提供一种自动创建实例的方法?
通过在您的 Spring 配置中定义它:
@Bean
public Foo<String> foo() {
return new Foo<>("bar");
}
或者您可以指定类型而不是值:
@Bean
public Foo<String> foo() {
return new Foo<>(String.class);
}
如果你使用Spring引导,你可以添加@ConditionalOnProperty
或@ConditionalOnBean
来动态化bean实例化。
(更新)如果你想避免声明,你应该扩展DefaultListableBeanFactory
和ApplicationContext
。这是 Spring Boot 的工作示例:
@Controller
@EnableAutoConfiguration
public class BeanFactoryTest {
public static void main(String[] args) throws Exception {
SpringApplication app = new SpringApplication(BeanFactoryTest.class);
app.setApplicationContextClass(CustomAppContext.class);
app.run(args);
}
@Autowired
private Foo<String> foo1;
@Autowired
private Foo<String> foo2;
@Autowired
private Foo<Integer> foo3;
@PostConstruct
public void initialize() {
System.out.println(foo1); // prints BeanFactoryTest$Foo@344b8190
System.out.println(foo2); // prints BeanFactoryTest$Foo@344b8190
System.out.println(foo3); // prints BeanFactoryTest$Foo@5b69d40d
}
public static class CustomAppContext extends AnnotationConfigApplicationContext {
public CustomAppContext() {
super(new CustomBeanFactory());
}
}
public static class CustomBeanFactory extends DefaultListableBeanFactory {
@Override
protected Map<String, Object> findAutowireCandidates(String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
Map<String, Object> map = super.findAutowireCandidates(beanName, requiredType, descriptor);
if (Foo.class.isAssignableFrom(requiredType)) {
ResolvableType type = ResolvableType.forField(descriptor.getField());
ResolvableType genericType = type.getGeneric(0);
Class<?> genericTypeRaw = genericType.getRawClass();
boolean hasInstance =
map.values()
.parallelStream()
.map(Foo.class::cast)
.map(Foo::getType)
.filter(genericTypeRaw::isAssignableFrom)
.findFirst()
.isPresent();
if (!hasInstance) {
super.registerResolvableDependency(requiredType, new Foo<>(genericTypeRaw));
map = super.findAutowireCandidates(beanName, requiredType, descriptor);
}
}
return map;
}
}
public static class Foo<T> {
private final Class<T> type;
public Foo(Class<T> type) {
this.type = type;
}
public Class<T> getType() {
return type;
}
}
}
看来你可以使用 Spring 中的 ResolvableType 4. http://docs.spring.io/spring/docs/4.0.0.RC2/javadoc-api/org/springframework/core/ResolvableType.html There is also a detail sample https://spring.io/blog/2013/12/03/spring-framework-4-0-and-java-generics
希望对您有所帮助。
这个问题有点老,但没有包含示例的答案,所以...
使用 ResolvableType:
public <E> Foo<E> produceFoo(final InjectionPoint ip) {
ResolvableType resolved = ResolvableType.forField(ip.getField());
Foo<E> fooInstance = new FooImpl<>();
Class<E> parameterClass = (Class<E>) resolved.getGeneric(0).resolve();
fooInstance.doSomethingWithParametrized(parameterClass);
return fooInstance;
}
InjectionPoint cames from: import org.springframework.beans.factory.InjectionPoint;