J'ai une usine comme ci-dessous,
public final class Application {
private static IFoo foo;
public static IFoo getFoo(String bar)
{
// i need to inject bar to the constructor of Foo
// obvious i have to do something, not sure what
Injector injector = Guice.createInjector();
logger = injector.getInstance(Foo.class);
return logger;
}
}
Voici la définition de Foo:
class Foo
{
Foo(String bar)
{
}
}
D'ACCORD. Je ne sais pas comment je peux passer ce paramètre au constructeur Foo avec Guice?
Des idées?
Toutes les réponses "Guice Constructor Parameter" semblent être incomplètes d'une manière ou d'une autre. Voici une solution complète, y compris l'utilisation:
interface FooInterface{
String getFooName();
}
// Annoter le constructeur et les paramètres assistés sur la classe d'implémentation
class Foo implements FooInterface {
String bar;
@Inject
Foo(@Assisted String bar)
{
this.bar = bar;
}
// return the final name
getFooName(){
return this.bar;
}
}
// Créez une interface d'usine avec une méthode create () qui ne prend que les paramètres assistés.
// L'interface FooFactory n'a pas de classe d'implémentation explicite (Guice Magic)
interface FooFactory{
Foo create(String bar);
}
// Liez cette fabrique à un fournisseur créé par AssistedInject
binderModule implements Module{
void configure(Binder binder) {
binder.install(new FactoryModuleBuilder()
.implement(FooInterface.class, Foo.class)
.build(FooFactory.class));
}
}
// Maintenant, utilisez-le:
class FooAction{
@Inject private FooFactory fooFactory;
doFoo(){
// Send bar details through the Factory, not the "injector"
Foo f = fooFactory.create("This foo is named bar. How lovely!");
f.getFooName(); // "This foo is named bar. How lovely!"
}
}
Beaucoup d'aide ici: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html
Ce que vous cherchez probablement, c'est d'utiliser une usine Guice. Particulièrement facile avec la fonctionnalité AssistedInject
, mais ils ont un exemple manuel en haut de la page . Le raccourci pour l'exemple manuel est que vous obtenez l'usine sous la méthode non statique getFoo
que vous passez tous les paramètres dont vous avez besoin et construisez l'objet à partir de là.
Cela ne fonctionnera pas directement si vous avez une interception de méthode dans Foo
, mais cela fonctionnera dans de nombreux autres cas.
Pour utiliser AssistedInject
, qui pour moi a une sémantique quelque peu plus propre et signifie moins de câblage manuel, vous aurez besoin de l'extension guice-aidinject dans le chemin de classe, puis lors de la création de Foo
(enfin, FooImpl
, nous devrions utiliser des interfaces):
@Inject
public FooImpl(@Assisted String bar)
{
this.baz = bar;
}
Ensuite, vous créez une interface FooFactory
:
public interface FooFactory {
public Foo create(String bar);
}
Puis dans votre module guice:
install(new FactoryModuleBuilder()
.implement(Foo.class, FooImpl.class)
.build(FooFactory.class));
Vous pouvez consulter le javadoc pour FactoryModuleBuilder
pour des exemples avec des usines plus complexes.
Je sais que c'est du vieux fil, mais je viens de frapper le problème moi-même aujourd'hui. Je n'ai besoin que de deux ou maximum trois instances différentes de 'Foo' et je ne voulais vraiment pas écrire tout le code bolierplate de Factory. Avec un peu de recherche sur Google, j'ai trouvé cela Stubbisms - Tony’s Weblog Je suggérerais cette solution qui est parfaite si vous savez exactement de quelles instances vous avez besoin.
Dans le module Guice:
bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(new Provider<Foo>() {
@Override
public Foo get() {
return new FooImpl("topic A");
}
});
bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(new Provider<Foo>() {
@Override
public Foo get() {
return new FooImpl("topic B");
}
});
Ou en Java 8:
bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(() -> new FooImpl("first"));
bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(() -> new FooImpl("second"));
Et en constructeur de votre service où vous avez besoin d'instances Foo:
@Inject
public MyService (
@Named("firstFoo") Foo firstFoo,
@Named("secondFoo") Foo secondFoo) {
}
Et Foo dans mon cas:
public class FooImpl implements Foo {
private String name;
public FooImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
J'espère que cela aide quelqu'un.
Si cette classe est une fabrique, ce devrait être un objet géré par Guice, ayant une méthode getFoo non statique, et la méthode getFoo utiliserait simplement
new Foo(bar)
Guice n'a pas besoin d'instancier chaque classe.
Voir aussi AssistedInject , pour éviter de créer vous-même cette usine et laissez Guice en créer une pour vous.