java 获取本质上是原型的自动装配字段的新实例的更简洁方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10358035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 00:41:48  来源:igfitidea点击:

Cleaner way to get new instance of an autowired field that is prototype in nature

javaspringautowiredillegalstateexception

提问by instanceOfObject

I faced this issue, while trying to autowire a runnable class and creating different instances of it in different call and keeping it in an array.

我在尝试自动装配一个可运行的类并在不同的调用中创建它的不同实例并将其保存在数组中时遇到了这个问题。

xml configuration is :

xml配置是:

<bean name="threadName" Class="ABC" scope="prototype" />

In my code, I am trying something like this:

在我的代码中,我正在尝试这样的事情:

public class ThreadHandler{


@Autowired
private ABC threadName;

//getter
ABC getThreadName(){
     return threadName;
}

public void someFunction(){
     List<ABC> abc = new ArrayList(ABC>();
     for (int i=0;i<SOME_CONST;i++){
          ABC tName = getThreadName();
          abc.add(tName);
          tName.start();
      }
}   

}

}

Let ABCbe a class which is Thread/Runnable/Callable.

ABC是一个类是Thread/Runnable/Callable.

In this way, it throws java.lang.IllegalThreadStateException. But, it works fine, if I use ABC tName =appContext.getBean("threadName",ABC.class);

这样,它抛出java.lang.IllegalThreadStateException. 但是,它工作正常,如果我使用ABC tName =appContext.getBean("threadName",ABC.class);

Why does it happen?

为什么会发生?

Don't we get a new instance while trying to get an object from getMethod?

我们在尝试从 getMethod 获取对象时不是得到了一个新实例吗?

回答by danny.lesnik

There is much better practice when you need to create Runnable/Callable and inject it into applicationContext it's called look up method:

当您需要创建 Runnable/Callable 并将其注入 applicationContext 时,有更好的做法,它称为查找方法:

Let's consider that all Runnable/Callable classes are @Prototype and @Lazy

让我们考虑所有 Runnable/Callable 类都是 @Prototype 和 @Lazy

@Component(value="task")
@Scope(value="prototype")
@Lazy(value=true)
public class Task implements Runnable {

public void run(){
.....
}

}

Now you need to Create Look up method factory:

现在您需要创建查找方法工厂:

    <bean id="taskFactory" class="x.y.z.TaskFactory">
<lookup-method name="createTask" bean="task"/>
</bean>

Now let's implement TaskFactory itself which is abstract class and have one abstract method :

现在让我们实现 TaskFactory 本身,它是抽象类并有一个抽象方法:

@Component(value="taskFactory")
public abstract class TaskFactory {

    public abstract Task createTask();

}

Here comes the magic:

魔法来了:

public class ThreadHandler{

@Autowired
private TaskFactory taskFactory;


public void someFunction(){
          Runnable task = taskFactory.createTask();
          taskExecutor.execute(task);
      }
}   

Every time you are calling createTask() method of taskFactory singleton object. you will receive completely new instanceof your prototype object.

每次调用 taskFactory 单例对象的 createTask() 方法时。您将收到原型对象的全新实例

P.S: don't forget to add

PS:不要忘记添加

<context:annotation-config />
    <context:component-scan base-package="x.y.z"></context:component-scan>

to enable Annotations correctly.

正确启用注释。

hope it Helps.

希望能帮助到你。

回答by Affe

No, you don't get a new object, just by accessing a field that holds a reference to a bean scoped as Prototype. Spring doesn't have any way to replace your instance level reference with a new reference based just on field access. It's set once by the autowiring and then it's just a reference to that one object. If you want it to actually create a new one you need to use getBean as you observed.

不,您不会得到一个新对象,只是通过访问一个包含对范围为 Prototype 的 bean 的引用的字段。Spring 没有任何方法仅基于字段访问将您的实例级引用替换为新引用。它由自动装配设置一次,然后它只是对那个对象的引用。如果您希望它实际创建一个新的,则需要按照您的观察使用 getBean。

You can tell Spring to override your get method and replace it with a 'getBean' using method injection, to get the Spring dependencies out of your bean:

您可以告诉 Spring 覆盖您的 get 方法并使用方法注入将其替换为“getBean”,以从您的 bean 中获取 Spring 依赖项:

<bean id="threadHandler" class="com.stackexchange.ThreadHandler">
<lookup-method name="getThreadName" bean="threadName"/>
</bean>