在即时化对象后,Guice调用init方法

mga*_*mer 62 init guice postconstruct

是否有可能告诉Guice在定时给定类型的对象后调用某个方法(即init())?

我在EJB 3中寻找类似于@PostConstruct注释的功能.

Sim*_*son 61

您只需将@Inject注释添加到init()方法中即可.在实例化对象后它将自动运行.

  • 问题是如果你有可选的依赖项,这种方法不起作用,因为据我所知,没有办法告诉guice将你的init()方法作为最后一种方法.恕我直言,他们需要@PostConstruct支持. (12认同)

gpa*_*ara 37

实际上,这是可能的.

您需要定义一个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();
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

  • Matchers.subclassesOf(MyInitClass.class)实际上会导致编译时错误:"AbstractModule类型中的方法bindListener(Matcher <?super TypeLiteral <?>>,TypeListener)不适用于参数(Matcher <Class>, new TypeListener(){})"我认为你必须扩展AbstractMatcher才能使你的代码工作 (8认同)
  • 同意,此示例包含编译错误.以下博客文章详细介绍了如何绑定侦听器:http://developer.vz.net/2012/02/08/extending-guice-2/ (7认同)
  • 另外一个选择是使用GuicyFruit,声称支持@PostConstruct(请参阅http://code.google.com/p/guiceyfruit/),虽然它没有回答这个问题,但我认为值得一提的是,如果你(单独)使用构造函数注入,你不需要这样的功能,因为你可以在构造函数中进行所有初始化. (4认同)

Geo*_*edy 7

guiceyfruit会为你注意@PostConstruct或实施spring的方法做些什么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);
      }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)