Подтвердить что ты не робот

Задачи Autowiring, отправленные в Spring TaskExecutor

Как у вас есть класс, который реализует Runnable и отправляется на пружины TaskExecutor, автоматически?

Например, у меня есть задача:

public class MyTask implements Runnable {

    @Autowired private MyRepository myRepository;

    @Override
    public void run() {
        myRepository.doSomething();
    }
}

И служба, которая отправляет задачу в spring TaskExecutor:

@Service
public class MyService {

    @Autowired private TaskExecutor taskExecutor;

    public void someMethod() {

        MyTask myTask = new MyTask();
        taskExecutor.execute(myTask);

    }

}

Я знаю, что поля не автообновлены, потому что MyTask получает экземпляр, используя новый MyTask(). Однако как мне обойти это? Должен ли я получить доступ к spring ApplicationContext и создать bean через него? Как вы это сделаете в среде веб-приложения?

Спасибо!

4b9b3361

Ответ 1

Есть как минимум два хороших способа сделать это, используя Spring. Во-первых, @Configurable аннотация. Использование этого означает зависимость от AspectJ, но это позволит вам вводить beans, которые не управляются с помощью Spring (т.е. Вы используете новый оператор). Это должно включать аннотирование MyTask с @Configurable и добавление пары строк в конфигурацию Spring, как указано в ссылке.

@Configurable
public class MyTask implements Runnable { ... }

@Service
public class MyService {
   @Autowired private TaskExecutor taskExecutor;

   public void someMethod() {

     // AspectJ would jump in here and inject MyTask transparently
     MyTask myTask = new MyTask();
     taskExecutor.execute(myTask);

}

}

Второй подход предполагает использование функции ServiceLocatorFactoryBean для Spring для создания прототипа beans. Это лучше всего объясняется в JavaDoc, но в этом случае вы должны ввести TaskFactory в свой аннотированный класс @Service, как и любой другой bean, а затем выполните примерно так:

@Service
public class MyService {
  @Autowired private TaskExecutor taskExecutor;
  @Autowired private MyRepository myRepository;
  @Autowired private TaskFactory taskFactory;


public void someMethod() {
    MyTask myTask = taskFactory.getTask("myTask")
    taskExecutor.execute(myTask);
}

}

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

Ответ 2

попробовать

public class MyTask implements Runnable {
    private MyRepository myRepository;

    public MyTask(MyRepository myRepository) {
         this.myRepository = myRepository;
    }

    @Override
    public void run() {
        myRepository.doSomething();
    }
}

@Service
public class MyService {
    @Autowired private TaskExecutor taskExecutor;
    @Autowired private MyRepository myRepository;


    public void someMethod() {
        MyTask myTask = new MyTask(myRepository);
        taskExecutor.execute(myTask);
    }
}

или вы можете объявить область MyTask = "prototype" и изменить MyService как

@Service
public class MyService {
    @Autowired private ApplicationContext ctx;

    public void someMethod() {
        MyTask myTask = ctx.getBean(MyTask.class);
        taskExecutor.execute(myTask);
    }
}