Використовуючи Java-конфігурацію Spring, мені потрібно придбати / інстанціювати прототип обміну з аргументами конструктора, які можна отримати лише під час виконання. Розглянемо наступний приклад коду (спрощений для стислості):
@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);
}
Тепер, я міг би створити завод, наприклад:
public interface ThingFactory {
public Thing createThing(String name);
}
Але це перемагає всю точку використання Spring для заміни моделі дизайну ServiceLocator та Factory , що було б ідеально підходить для цього випадку використання.
Якби Spring Java Config міг це зробити, я міг би уникнути:
- визначення фабричного інтерфейсу
- визначення реалізації заводу
- написання тестів для впровадження на заводі
Це багато роботи (відносно кажучи) для чогось настільки тривіального, що Spring вже підтримує через конфігурацію XML.
Thing
реалізація насправді є більш складною і має залежність від інших бобів (я їх просто опустив для стислості). Тому я не хочу, щоб реалізація обробника запиту знала про них, оскільки це щільно з'єднає обробник з API / бобами, які йому не потрібні. Я оновлю питання, щоб відобразити ваше (відмінне) запитання.
@Qualifier
параметри для сеттера з @Autowired
самим сеттером.
@Bean
творами. @Bean
Метод викликається з відповідними аргументами , переданими getBean(..)
.