Spring FactoryBean and scopes working together

匿名 (未验证) 提交于 2019-12-03 02:52:02

问题:

I'd like to use FactoryBeans and scopes together. Specifically, I'd like the object created and returned by a FactoryBean to be placed into a specified (perhaps custom) scope. The issue is that doing the following:

<bean class="x.y.z.TestFactoryBean" scope="test" /> 

Results in the FactoryBean itself being scoped, and has somewhat unpredictable behaviour on the object created by the factory. I understand why this is; the factory itself is a first-class spring-managed bean, and has its own lifecycle. However, I can't find a way to specify that the object returned from the factory should itself be scoped.

On the other hand, this does exactly what I want (as long as TestFactoryBean does NOT implement the FactoryBean interface):

<bean class="x.y.z.TestFactoryBean" name="testFactory"> <bean class="x.y.z.TestBean" factory-bean="testFactory"        factory-method="getObject" scope="test" /> 

So the real question is, how can I make Spring behave like it does for the 2nd example above, but using real FactoryBeans?

回答1:

You can't easily use a custom scope on a bean returned from a FactoryBean.

From Spring's Java documentation:

FactoryBeans can support singletons and prototypes

If you want the FactoryBean's returned bean to have the prototype scope, then you must implement the isSingleton() method like this:

public class TestFactoryBean implements FactoryBean<TestBean> {    // the rest of the required methods are removed for simplicity reasons..    public boolean isSingleton() {         return false;     } } 

To support a custom scope, you have to implement the logic yourself and it will not be very intuitive, since the FactoryBean only provides the isSingleton() method. I will rather recommend using another solution than FactoryBean for beans with custom scope.

Hope this helps!



回答2:

I solved the same issue using custom holder bean.

Factory 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;     } } 

And then I use holder instead of the required entity.

@Component @Configurable @Scope("session") public class UicPlaceController extends PlaceController {      @Autowired     public UicPlaceController(EventBusHolder eventBus) {         super(eventBus.getEventBus());     }     ...  } 

The solution looks a little bit ugly, but still, it solves the issue.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!