Вопрос по spring, java – Более чистый способ получить новый экземпляр автопроводного поля, который является прототипом в природе

2

Я столкнулся с этой проблемой, пытаясь автоматически связать исполняемый класс, создавая его различные экземпляры в разных вызовах и сохраняя его в массиве.

онфигурация @xml:

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

В моем коде я пытаюсь что-то вроде этого:

public class ThreadHandler{


@Autowired
private ABC threadName;

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

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

}

ПозволятьABC будь классом, который естьThread/Runnable/Callable.

Таким образом, он бросаетjava.lang.IllegalThreadStateException. Но это работает нормально, если я используюABC tName =appContext.getBean("threadName",ABC.class);

Почему это происходит?

Разве мы не получаем новый экземпляр при попытке получить объект из getMethod?

Тебе не нужен добытчик. просто используйте this.threadName.someFinction (); danny.lesnik
Вы имеете в виду, this.threadName всегда будет давать новый экземпляр? точно, как appContext.getBean ("имя", класс) делает? instanceOfObject

Ваш Ответ

2   ответа
6

когда вам нужно создать Runnable / Callable и вставить его в applicationContext, он называется методом поиска:

Давайте рассмотрим, что все классы Runnable / Callable являются @Prototype и @ Lazy

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

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

}

Теперь вам нужно создать фабрику методов поиска:

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

Теперь давайте реализуем сам TaskFactory, который является абстрактным классом и имеет один абстрактный метод:

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

    public abstract Task createTask();

}

Вот приходит волшебство:

public class ThreadHandler{

@Autowired
private TaskFactory taskFactory;


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

Каждый раз, когда вы вызываете метод createTask () одноэлементного объекта taskFactory. ты получишь совершенно новый экземпляр вашего объекта-прототипа.

P.S: не забудьте добавить

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

для правильного включения аннотаций.

Надеюсь, это поможет

1

вы не получаете новый объект, просто обращаясь к полю, которое содержит ссылку на bean-объект, определяемый как Prototype. Spring не имеет никакого способа заменить ссылку на ваш экземпляр уровня новой ссылкой, основанной только на доступе к полю. Он устанавливается один раз с помощью автоматического подключения, а затем это просто ссылка на этот один объект. Если вы хотите, чтобы он действительно создал новый, вам нужно использовать getBean, как вы заметили.

Вы можете указать Spring переопределить ваш метод get и заменить его на getBean, используя инъекцию метода, чтобы получить зависимости Spring от вашего компонента:

<bean id="threadHandler" class="com.stackexchange.ThreadHandler">
<lookup-method name="getThreadName" bean="threadName"/>
</bean>
Да, имеет смысл, и это то, что я тоже заметил. Но есть ли более чистый способ, чем вызов appContext.getBean («имя», класс)? Или это единственный возможный способ? instanceOfObject
Да, вы можете использовать метод инъекции, чтобы Spring генерировал бин в ответ на метод получения: Affe

Похожие вопросы