Каков правильный прокси-режим Бина для разрешения параллелизма в Spring?

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

В моем основном классе я с автопроводом. Класс обслуживания:

@Autowired
private ExportListCommand exportList;

И это реализация метода библиотеки:

public ResponseContainer<ExportListResponse> exportList(ExportListOptions options) {
    exportList.setoAuthClient(oAuthClient);
    ResponseContainer<ExportListResponse> result = exportList.executeCommand(options);

    return result;
}

ExportListCommand определяется как Бин:

@Bean
@Scope("prototype")
public ExportListCommand exportList() {
    return new ExportListCommand();
}

Когда я как пользователь библиотеки запускаю 2 метода exportList параллельно, Spring создает только один ExportListCommand боб, так как он подключен только один раз. Но на самом деле мне нужно 2 независимых ExportListCommand фасоль. Я тоже пытался изменить @Scope(value="prototype") в @Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS), но это также не работает, как мне нужно: Spring создает ExportListCommand бин для каждого вызова метода, и я теряю oAuthClient значение, так как я получаю новый объект.

Я сделал это работать только с AnnotationConfigApplicationContext.getBean() подход, которого я хотел бы избежать.

Какие у меня есть варианты? Благодарю.

1 ответ

Я считаю, что вы ищете для работы с "фабричным" объектом.

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

  1. Способ "Java": создайте объект фабрики, который будет возвращать экземпляры ExportListCommand

Эта фабрика будет выглядеть примерно так:

class ExportListCommandFactory {
    ExportListCommand newInstance() {
        return new ExportListCommand();
    }
}

и будет использоваться в вашем методе так:

@Autowire
private ExportListCommandFactory commandFactory;

public ResponseContainer<ExportListResponse> exportList(ExportListOptions options) {
    final ExportListCommand exportList = commandFactory.newInstance();
    exportList.setoAuthClient(oAuthClient);
    ResponseContainer<ExportListResponse> result = exportList.executeCommand(options);

    return result;
}

Конечно, для этого потребуется изменить конфигурацию, чтобы она содержала компонент, который является ExportListCommandFactory а не ExportListCommand,

В качестве альтернативы, вы могли бы рассмотреть...

  1. "Весенний" способ: использование FactoryBean

Единственное, что вам нужно сделать здесь, в вашем основном классе, @Autowire FactoryBean<ExportListCommand> вместо ExportListCommand и в вашем методе, где вам нужно вызвать метод, обратитесь к фабрике, чтобы получить ваш экземпляр.

@Autowire
private FactoryBean<ExportListCommand> commandFactory;

public ResponseContainer<ExportListResponse> exportList(ExportListOptions options) {
    final ExportListCommand exportList = commandFactory.getObject();
    exportList.setoAuthClient(oAuthClient);
    ResponseContainer<ExportListResponse> result = exportList.executeCommand(options);

    return result;
}

Вам не нужно изменять свою конфигурацию, поскольку FactoryBean - это специальный компонент, который будет обращаться к ApplicationContext/BeanFactory для экземпляра при каждом вызове getObject(),

Другие вопросы по тегам