Utilizzando Spring Config di Spring, ho bisogno di acquisire / creare un'istanza di un bean con ambito prototipo con argomenti di costruzione ottenibili solo in fase di esecuzione. Considera il seguente esempio di codice (semplificato per brevità):
@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
}
dove la classe Thing è definita come segue:
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;
}
}
Avviso name
è final
: può essere fornito solo tramite un costruttore, e garantisce l'immutabilità. Le altre dipendenze sono dipendenze della Thing
classe specifiche dell'implementazione e non dovrebbero essere note all'implementazione del gestore richieste (strettamente accoppiato a).
Questo codice funziona perfettamente con la configurazione Spring XML, ad esempio:
<bean id="thing", class="com.whatever.Thing" scope="prototype">
<!-- other post-instantiation properties omitted -->
</bean>
Come ottengo la stessa cosa con la configurazione Java? Quanto segue non funziona utilizzando Spring 3.x:
@Bean
@Scope("prototype")
public Thing thing(String name) {
return new Thing(name);
}
Ora potrei creare una fabbrica, ad esempio:
public interface ThingFactory {
public Thing createThing(String name);
}
Ma questo sconfigge l'intero punto dell'uso di Spring per sostituire il modello di progettazione ServiceLocator e Factory , che sarebbe l'ideale per questo caso d'uso.
Se Spring Java Config potesse fare questo, sarei in grado di evitare:
- definire un'interfaccia Factory
- definire un'implementazione in fabbrica
- scrivere test per l'implementazione in fabbrica
È un sacco di lavoro (relativamente parlando) per qualcosa di così banale che Spring supporta già tramite la configurazione XML.
Thing
implementazione è in realtà più complessa e ha dipendenze da altri bean (li ho appena omessi per brevità). Pertanto, non voglio che l'implementazione del gestore richieste ne sia a conoscenza, poiché ciò accoppierebbe strettamente il gestore alle API / bean che non è necessario. Aggiornerò la domanda per riflettere la tua (eccellente) domanda.
@Qualifier
parametri su un setter con @Autowired
sul setter stesso.
@Bean
opere. Il @Bean
metodo viene chiamato con gli argomenti appropriati passati getBean(..)
.