Question

Est-il possible de dire Guice d'appeler une méthode (à savoir init ()) après instantinating un objet de type donné?

Je cherche des fonctionnalités similaires à @PostConstruct annotation dans EJB 3.

Était-ce utile?

La solution

En fait, il est possible.

Vous devez définir un TypeListener pour obtenir la fonctionnalité en cours. Quelque chose le long des lignes de ce qui suit dans votre définition du module:

bindListener(Matchers.subclassesOf(MyInitClass.class), new TypeListener() {
    @Override
    public <I> void hear(final TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) {
        typeEncounter.register(new InjectionListener<I>() {
            @Override
            public void afterInjection(Object i) {
                MyInitClass m = (MyInitClass) i;
                m.init();
            }
        });
    }
});

Autres conseils

Vous pouvez simplement ajouter l'annotation @Inject à votre méthode de init(). Il va se exécuter automatiquement après que l'objet est instancié.

guiceyfruit fait ce que vous êtes après des méthodes annotées avec @PostConstruct ou la mise en œuvre de InitializingBean de printemps . Il est également possible d'écrire vos propres auditeurs de le faire. Voici un exemple qui appelle une méthode init() public après les objets sont créés.

import com.google.inject.*;
import com.google.inject.matcher.*;
import com.google.inject.spi.*;

public class MyModule extends AbstractModule {
  static class HasInitMethod extends AbstractMatcher<TypeLiteral<?>> {
    public boolean matches(TypeLiteral<?> tpe) {
      try {
        return tpe.getRawType().getMethod("init") != null;
      } catch (Exception e) {
        return false;
      }
    }

    public static final HasInitMethod INSTANCE = new HasInitMethod();
  }

  static class InitInvoker implements InjectionListener {
    public void afterInjection(Object injectee) {
      try {
        injectee.getClass().getMethod("init").invoke(injectee);
      } catch (Exception e) {
        /* do something to handle errors here */
      }
    }
    public static final InitInvoker INSTANCE = new InitInvoker();
  }

  public void configure() {
    bindListener(HasInitMethod.INSTANCE, new TypeListener() {
      public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
        encounter.register(InitInvoker.INSTANCE);
      }
    });
  }
}

GWizard comprend un module (gwizard-services) qui fournit des services de goyave dans un format Guice convivial. services de Goyave vous donner la gestion du cycle de vie dans les discussions parallèles.

https://github.com/stickfigure/gwizard

Si vous souhaitez appeler une méthode après la construction d'une instance, cela signifie que l'appel de méthode post-construction est en fait une étape de la création d'instance. Dans ce cas, je recommanderais modèle de conception d'usine abstraite pour résoudre ce problème. Le code peut ressembler à quelque chose comme ceci:


class A {
    public A(Dependency1 d1, Dependency2 d2) {...}

    public postConstruct(RuntimeDependency dr) {...}
}

interface AFactory {
    A getInstance(RuntimeDependency dr);
}

class AFactoryImpl implements AFactory {
    @Inject
    public AFactoryImpl(Dependency1 d1, Dependency2 d2) {...}

    A getInstance(RuntimeDependency dr) {
        A a = new A(d1, d2);
        a. postConstruct(dr);
        return a;
    }
}

// in guice module
bind(AFactory.class).to(AFactoryImpl.class)

Si vous avez besoin d'initialiser un objet à l'aide d'autres objets et après que les deux sont prêts (ce qui est le cas si vous devez vous inscrire un avec l'autre et ils dépendent aussi de l'autre), vous pouvez facilement le faire comme ceci:

public final class ApplicationModule extends AbstractModule {

  @Override
  protected void configure() {
    requestStaticInjection(ApplicationModule.class);
  }

  @Inject
  static void injectApplication(
      ReslSession reslSession,
      Set<Saga> sagas,
      Set<Reaction> reactions
  ) {
    sagas.forEach(reslSession::registerSaga);
    reactions.forEach(reslSession::registerReaction);
  }

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top