春天通用豆工厂

问题描述 投票:1回答:3

Spring中是否有一种机制可以为通用bean构建提供自动化方法?

例如,如果我有类定义,如:

class Foo<T> {
    private final T type;
    ...
}

和依赖性:

@Autowired
private Foo<String> foo;

我想在Spring中使用一些机制,它以某种形式提供来自依赖关系定义的T(在上面的例子中,String)并提供一种自动实例创建的方法?

java spring spring-java-config
3个回答

1
投票

通过在Spring配置中定义它:

@Bean
public Foo<String> foo() {
    return new Foo<>("bar");
}

或者代替值,您可以指定类型:

@Bean
public Foo<String> foo() {
    return new Foo<>(String.class);
}

如果使用Spring Boot,则可以添加@ConditionalOnProperty@ConditionalOnBean来动态化bean实例化。

(更新)如果你想避免声明,你应该扩展DefaultListableBeanFactoryApplicationContext。以下是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;
        }
    }
}

0
投票

这个问题有点陈旧,但不包含例子中的答案,所以...

使用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来自:import org.springframework.beans.factory.InjectionPoint;

© www.soinside.com 2019 - 2024. All rights reserved.