我卡在了一个从纯Java到Spring的简单重构上。这个应用程序有一个“容器”对象,它在运行时实例化其部分。让我用代码来解释一下:
public class Container {
private List<RuntimeBean> runtimeBeans = new ArrayList<RuntimeBean>();
public void load() {
// repeated several times depending on external data/environment
RuntimeBean beanRuntime = createRuntimeBean();
runtimeBeans.add(beanRuntime);
}
public RuntimeBean createRuntimeBean() {
// should create bean which internally can have some
// spring annotations or in other words
// should be managed by spring
}
}
基本上,在加载容器时,容器会请求一些外部系统提供关于每个RuntimeBean
的数量和配置信息,并根据给定的规范创建这些bean。
问题是:通常在Spring中进行操作时。
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
Container container = (Container) context.getBean("container");
我们的对象已经完全配置并注入了所有依赖。但在我的情况下,我必须在执行load()方法后实例化一些需要依赖注入的对象。
我该如何实现呢?
我正在使用基于Java的配置,我已尝试为RuntimeBeans创建一个工厂:
public class BeanRuntimeFactory {
@Bean
public RuntimeBean createRuntimeBean() {
return new RuntimeBean();
}
}
期望使用@Bean
在所谓的“轻量级”模式下工作。http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Bean.html不幸的是,我发现与仅仅使用new RuntimeBean()没有什么区别。这里有一个类似问题的帖子:如何获取由FactoryBean创建且由Spring管理的bean?
还有http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Configurable.html,但在我的情况下看起来很笨重。我还尝试使用ApplicationContext.getBean(“runtimeBean”,args),其中runtimeBean具有“Prototype”范围,但getBean是一个糟糕的解决方案。
更新1
为了更具体,我正在尝试重构这个类: https://github.com/apache/lucene-solr/blob/trunk/solr/core/src/java/org/apache/solr/core/CoreContainer.java 参见#load()方法并查找“return create(cd,false);”
更新2
我在Spring文档中发现了一件相当有趣的事情,叫做“查找方法注入”: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-lookup-method-injection
还有一个有趣的jira票据https://jira.spring.io/browse/SPR-5192,Phil Webb在其中说https://jira.spring.io/browse/SPR-5192?focusedCommentId=86051&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-86051应该在这里使用javax.inject.Provider(它让我想起了Guice)。
更新3
更新4
所有这些“查找”方法的问题在于它们不支持传递任何参数。我也需要像使用applicationContext.getBean(“runtimeBean”,arg1,arg2)一样传递参数。好像在某个时候用https://jira.spring.io/browse/SPR-7431修复了这个问题。
更新5
Google Guice有一个很棒的功能叫做AssistedInject。https://github.com/google/guice/wiki/AssistedInject
@Bean
方法返回的,例如在配置类上,则不是这样。虽然这听起来很像一个XY问题,但Spring Cloud Connectors之类的东西可能是更好的选择。 - chrylis -cautiouslyoptimistic-Container
类及其对new
的使用。这在Spring中行不通。 - Kevin Bowersox