Spring FactoryBean和范围一起工作

时间:2010-05-13 21:11:55

标签: java spring

我想将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?

2 个答案:

答案 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());
    }
    ...
 }

解决方案看起来有点难看,但仍然解决了这个问题。