开发者

Creating beans on-demand using spring

I want to create some spring beans after startup in a factory-ish pattern. For example every so often I have some work to do and I need to create a task bean (which probably has dependents on other singleton spring beans) and execute it.

There may be several pieces of work to execute concurrently so each task bean needs to be independent (prototype).

Is there any common pattern people use to achieve this?

As I see it I need to interact with the container/applicationContext somehow but I don't really want to scatter injections of applicationContext/beanFactory and calls to getBean("...") everywhere.

I thought of something like this (note the "factory" is something I'm imagining, rather than something that exists)

<bean id="myTask" class="MyTask" scope="prototype">
  <property name="entityManager" ref=".../>
  ...
</bean>

<bean id="myTaskExecutor" class="MyTaskExecutor">
  <property name="taskFactory">
     <xxx:factory bean="myTask"/>
  </property>
</bean>

And then code

class MyTaskExecutor
{
  private Factory<MyTask> taskFactory;

  public void setTaskFactory( Factory<MyTask> taskFactory )
  {
    this.taskFactory = taskFactory;
  }
}

And maybe an annotation version

class MyTaskExecutor
{
  @Factory(MyTask.class)
  private Factory<MyTask> taskFactory;

}

Maybe there's something like the above already? Or am I missing something fundamental somewhere.

I realise I could have a singleton MyTaskFactory and use that to instantiate using "new" but then I开发者_开发技巧'd have to pass all of it's dependents from the factory which feels wrong.

So I guess to sum up the question is

What is the recommended way of creating prototype spring beans on-demand from within application code?

Appreciate any input.


I think you're over-complicating the problem. All you need to do is write a TaskFactory class (nothing special about it, no special interfaces or annotations). TaskFactory would be injected with all the other beans needed, and would have a createTask method which creates the tasks on demand, and which passes references to the required Spring beans to the new task when it's created. Client code is injected with TaskFactory, and calls createTask when required.

Spring itself provides no explicit support for what you're trying to do. The likes of factory-method XML attributes and FactoryBean interfaces are only useful for one-off creation of a bean within its scope, and if you want to create them on demand, that means scope="prototype", and that means using getBean().

edit: It's probably worth pointing out that prototype-scoped beans are really not what Spring is designed for. Yes, it supports them, but using them is not a very edifying experience. If you really want to go down this road, then it's worth taking a look at @Configurable. It's very powerful, but not always suitable, because of runtime classloader constraints.


I'm trying to do a very similar thing (Spring 3.0) to this so I'd be interested in hearing how you ended up solving this problem.

My current approach is to use getBean() and I've gone with the default singleton scope with my Spring-instatiated beans/pojos. So I have non-thread safe code for now but would like to improve it to be thread safe further down the track.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜