我想将FactoryBeans和范围一起使用。具体来说,我希望FactoryBean创建并返回的对象放在指定的(可能是自定义的)范围内。问题是执行以下操作:
<bean class="x.y.z.TestFactoryBean" scope="test" />
FactoryBean本身的结果是作用域,并且在工厂创建的对象上有一些不可预测的行为。我明白为什么会这样;工厂本身是一流的春季管理的豆,并有自己的生命周期。但是,我找不到一种方法来指定从工厂返回的对象本身应该是作用域。
另一方面,这完全符合我的要求(只要TestFactoryBean不实现FactoryBean接口):
<bean class="x.y.z.TestFactoryBean" name="testFactory">
<bean class="x.y.z.TestBean" factory-bean="testFactory"
factory-method="getObject" scope="test" />
所以真正的问题是,我如何使Spring的行为与上面的第二个例子一样,但是使用真正的FactoryBeans?
答案 0 :(得分:6)
您无法在从FactoryBean
返回的bean上轻松使用自定义作用域。
来自Spring的Java documentation:
FactoryBeans可以支持单例和原型
如果您希望FactoryBean
的返回bean具有原型范围,那么您必须实现isSingleton()
方法,如下所示:
public class TestFactoryBean implements FactoryBean<TestBean> {
// the rest of the required methods are removed for simplicity reasons..
public boolean isSingleton() {
return false;
}
}
要支持自定义作用域,您必须自己实现逻辑并且它不会非常直观,因为FactoryBean
仅提供isSingleton()
方法。对于具有自定义范围的bean,我建议使用除FactoryBean
之外的其他解决方案。
希望这有帮助!
答案 1 :(得分:2)
我使用自定义持有者bean解决了同样的问题。
工厂bean:
@Component
@Configurable()
public class EventBusFactory implements FactoryBean<EventBus> {
@Override
public EventBus getObject() throws Exception {
return new SimpleEventBus();
}
@Override
public Class<?> getObjectType() {
return EventBus.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
Bean holder:
@Configurable
@Component
@Scope("session")
public class EventBusHolder {
@Autowired
private EventBus eventBus;
public EventBus getEventBus() {
return eventBus;
}
public void setEventBus(EventBus eventBus) {
this.eventBus = eventBus;
}
}
然后我使用holder而不是所需的实体。
@Component
@Configurable
@Scope("session")
public class UicPlaceController extends PlaceController {
@Autowired
public UicPlaceController(EventBusHolder eventBus) {
super(eventBus.getEventBus());
}
...
}
解决方案看起来有点难看,但仍然解决了这个问题。