Guice вызывает метод init после мгновенного запуска объекта - PullRequest
58 голосов
/ 19 января 2010

Можно ли сказать Guice вызывать некоторый метод (т.е. init ()) после мгновенный объект данного типа?

Я ищу функциональность, аналогичную аннотации @PostConstruct в EJB 3.

Ответы [ 7 ]

57 голосов
/ 20 мая 2011

Вы можете просто добавить аннотацию @Inject к своему методу init(). Он будет запущен автоматически после создания объекта.

34 голосов
/ 19 января 2010

На самом деле, это возможно.

Вам нужно определить TypeListener, чтобы функционал работал. Что-то вроде следующего в определении вашего модуля:

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();
            }
        });
    }
});
7 голосов
/ 15 апреля 2011

Мне нравится http://code.google.com/p/mycila/wiki/MycilaGuice. Это поддерживает Guice 3, кроме http://code.google.com/p/guiceyfruit.

7 голосов
/ 19 января 2010

guiceyfruit делает то, что вам нужно для методов, помеченных @PostConstruct или для реализации пружины InitializingBean. Также возможно написать своих собственных слушателей, чтобы сделать это. Вот пример, который вызывает публичный метод init() после создания объектов.

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);
      }
    });
  }
}
1 голос
/ 22 января 2015

GWizard включает модуль (gwizard-services), который предоставляет услуги Guava в удобном для Guice формате. Службы Guava обеспечивают управление жизненным циклом в параллельных потоках.

https://github.com/stickfigure/gwizard

0 голосов
/ 14 мая 2019

Если вы хотите вызвать метод после создания экземпляра, это означает, что вызов метода после конструирования фактически является этапом создания экземпляра. В этом случае я бы порекомендовал абстрактный шаблон фабричного дизайна для решения этой проблемы. Код может выглядеть примерно так:


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)
0 голосов
/ 03 апреля 2019

Если вам нужно инициализировать объект, используя другие объекты, и после того, как оба будут готовы (что в случае, если вам нужно зарегистрировать один объект на другом, и они также зависят друг от друга), вы можете легко сделать это следующим образом:

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);
  }

}
...