Используя Spring Java Config, мне нужно получить / создать экземпляр bean-компонента с прототипом с аргументами конструктора, которые доступны только во время выполнения. Рассмотрим следующий пример кода (упрощенный для краткости):
@Autowired
private ApplicationContext appCtx;
public void onRequest(Request request) {
//request is already validated
String name = request.getParameter("name");
Thing thing = appCtx.getBean(Thing.class, name);
//System.out.println(thing.getName()); //prints name
}
где класс Thing определяется следующим образом:
public class Thing {
private final String name;
@Autowired
private SomeComponent someComponent;
@Autowired
private AnotherComponent anotherComponent;
public Thing(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
Обратите внимание , name
это final
: он может быть поставлен только через конструктор, и гарантирует неизменность. Другие зависимости являются зависимостями Thing
класса, зависящими от реализации , и не должны быть известны (тесно связаны) с реализацией обработчика запросов.
Этот код отлично работает с конфигурацией Spring XML, например:
<bean id="thing", class="com.whatever.Thing" scope="prototype">
<!-- other post-instantiation properties omitted -->
</bean>
Как добиться того же с конфигурацией Java? Следующее не работает с использованием Spring 3.x:
@Bean
@Scope("prototype")
public Thing thing(String name) {
return new Thing(name);
}
Теперь я мог бы создать Factory, например:
public interface ThingFactory {
public Thing createThing(String name);
}
Но это лишает смысла использование Spring для замены шаблонов проектирования ServiceLocator и Factory , которые были бы идеальными для этого варианта использования.
Если бы Spring Java Config мог это сделать, я бы смог избежать:
- определение интерфейса Factory
- определение реализации Factory
- написание тестов для реализации Factory
Это тонна работы (условно говоря) для чего-то столь тривиального, что Spring уже поддерживает через конфигурацию XML.
Thing
реализация на самом деле более сложная и имеет зависимости от других bean-компонентов (я просто опустил их для краткости). Таким образом, я не хочу, чтобы реализация обработчика запросов знала о них, поскольку это жестко связывает обработчик с API / bean-компонентами, которые ему не нужны. Я обновлю вопрос, чтобы отразить ваш (отличный) вопрос.
@Qualifier
параметры для установщика с помощью @Autowired
самого установщика.
@Bean
works. @Bean
Метод вызывается с соответствующими аргументами , переданными getBean(..)
.