可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.