Spring:如何实例化一个采用运行时参数的Spring bean?

时间:2012-02-24 11:10:03

标签: java spring parameters prototype

我有一个单独的Spring bean,它在运行时创建了几个任务(java.util.concurrent.Callable)来并行完成它的工作。现在,Callable被定义为单例bean中的内部类,而单例bean仅通过使用new Task(in)实例化它们来创建它们,其中in是仅在运行时。

现在我想将内部Task类提取到常规顶级类,因为我想让Task的call()方法成为事务性的,所以我需要它成为一个Spring bean。

我想我需要为我的单例提供Task s的某种工厂,但任务必须是原型Spring bean,它将运行时值作为构造函数参数。我怎么能做到这一点?

3 个答案:

答案 0 :(得分:4)

另一种方法可能是使用Spring的@Configurable注释和加载时编织,这样你就可以使用new(而不是bean工厂)在运行时创建有线Callable:

@Configurable
public class WiredTask implements Callable<Result> {

    @Autowired
    private TaskExecutor executor;

    public WiredTask(String in) {
        this.in = in;
    }

    public Result call() {
        return executor.run(in);
    }
}

@Bean @Scope("prototype")
public class TaskExecutor() {

    @Transactional
    public Result run(String in) {
        ...
    }
}

// Example of how you might then use it in your singleton...
ExecutorService pool = Executors.newFixedThreadPool(3);
WiredTask task = new WiredTask("payload");
Future<Result> result = pool.submit(task);

有关详细信息,请参阅this article。注意,你不能使用@Configurable and @Transactional in the same bean,因此需要两个类。因此,如果您有许多不同的Callable实现,这可能不是理想的解决方案(因为每个类需要2个类)。

答案 1 :(得分:3)

您的单例bean可以从包含的spring工厂实现BeanFactoryAware和查找bean。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

public class MyBeanFactory implements BeanFactoryAware {

    private BeanFactory beanFactory;

    public void setBeanFactory(BeanFactory beanFactory) 
            throws BeansException    {
        this.beanFactory = beanFactory;     
    }

    public Task createTask(Task in) {
        return beanFactory.getBean("task",in);
    }

}
///////////////

import java.util.concurrent.Callable;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Scope;
import org.springframework.transaction.annotation.Transactional;

@Configurable // unless using xml based config
@Scope(value="prototype") // tell bean factory to create new instance each time
public class Task implements Callable<Object> {

    private Object in;

    public Task(Object in) {
        super();
        this.in = in;
    }

    @Transactional
    public Object call() throws Exception {
        //do real work
        return in;
    }   
}
///

答案 2 :(得分:2)

Spring的bean工厂和新工厂相互排斥。你不能调用new并期望该对象受Spring控制。

我的建议是将这些任务注入Singleton。让它们成为春豆。

您应该认识到Task本身不是事务,但它的依赖关系可以是。将这些注入任务并让Spring管理事务。