Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring:如何实例化接受运行时参数的Springbean?_Java_Spring_Parameters_Prototype - Fatal编程技术网

Java Spring:如何实例化接受运行时参数的Springbean?

Java Spring:如何实例化接受运行时参数的Springbean?,java,spring,parameters,prototype,Java,Spring,Parameters,Prototype,我有一个单例Springbean,它在运行时创建两个任务(java.util.concurrent.Callable),以并行地完成它的工作。现在,Callable被定义为singleton bean中的内部类,singleton bean通过使用new Task(in)实例化它们来创建它们,其中in是一个只有在运行时才知道的参数 现在,我想将内部任务类提取到一个常规的顶级类,因为我想使任务的call()方法具有事务性,所以我需要它是一个Springbean 我想我需要给我的单例提供某种工厂的T

我有一个单例Springbean,它在运行时创建两个任务(
java.util.concurrent.Callable
),以并行地完成它的工作。现在,
Callable
被定义为singleton bean中的内部类,singleton bean通过使用
new Task(in)
实例化它们来创建它们,其中
in
是一个只有在运行时才知道的参数

现在,我想将内部任务类提取到一个常规的顶级类,因为我想使任务的
call()
方法具有事务性,所以我需要它是一个Springbean


我想我需要给我的单例提供某种工厂的
Task
s,但是这些任务必须是原型Springbean,以运行时值作为构造函数参数。我怎样才能做到这一点呢?

Spring的bean factory和new是相互排斥的。您不能调用new并期望该对象在Spring的控制下

我的建议是将这些任务注入Singleton。也要做春豆


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

您的单例bean可以从包含Spring的工厂实现BeanFactoryAware和lookup 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;
    }   
}
///
import org.springframework.beans.BeansException;
导入org.springframework.beans.factory.BeanFactory;
导入org.springframework.beans.factory.BeanFactoryAware;
公共类MyBeanFactory实现BeanFactoryAware{
私人豆厂豆厂;
公共工厂(BeanFactory BeanFactory)
抛出BeansException{
this.beanFactory=beanFactory;
}
公共任务createTask(中的任务){
返回beanFactory.getBean(“任务”,in);
}
}
///////////////
导入java.util.concurrent.Callable;
导入org.springframework.beans.factory.annotation.Configurable;
导入org.springframework.context.annotation.Scope;
导入org.springframework.transaction.annotation.Transactional;
@可配置//除非使用基于xml的配置
@Scope(value=“prototype”)//每次告诉bean工厂创建新实例
公共类任务实现了可调用{
私人物品;
公共任务(中的对象){
超级();
this.in=in;
}
@交易的
公共对象调用()引发异常{
//干实事
返回;
}   
}
///

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

@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);
@可配置
公共类WiredTask实现了可调用{
@自动连线
私人任务执行者;
公共WiredTask(字符串输入){
this.in=in;
}
公共结果调用(){
返回执行器。运行(in);
}
}
@Bean@Scope(“原型”)
公共类任务执行器(){
@交易的
公共结果运行(字符串输入){
...
}
}
//然后你可以在你的单身生活中使用它的例子。。。
ExecutorService池=Executors.newFixedThreadPool(3);
WiredTask任务=新的WiredTask(“有效负载”);
未来结果=池。提交(任务);

有关更多信息,请参阅。注意,您不能使用,因此需要两个类。因此,如果您有许多不同的Callable实现,这可能不是理想的解决方案(因为每个实现需要两个类)。

@BorisTreukhov:这不是关于测试多线程应用程序的问题,而是关于Spring的问题。事实上,我将从我的问题中删除reason#2,因为它会分散对真实问题的注意力。请看:@Bossie ok我删除了我的评论,顺便说一句,我认为最简单的方法是创建单独的服务bean,将它们的方法装饰为事务性的,将它们注入到您的单例中,并将“In”参数传递给服务方法。+1表示KISS。没有理由让事情变得更加困难,只需创建事务性服务并将其注入到任务中。“Spring的bean factory和new是相互排斥的。”这对大多数人来说似乎是显而易见的,但对于一个Spring新手来说,这对我来说非常重要。它帮助我理解了spring的实际功能,但是如果我不知道任务的数量呢?也就是说,有人提交了一份带有数字的作业,比如说10,而我实例化了10个任务?您能告诉我在这种情况下如何将任务注入Singleton吗?您应该创建一个执行者池,让他们处理您的任务。忘掉单身汉,学习春天。