使用guice注入与actor抛出空指针

我在服务器的字段注入上获得空指针exception,该服务器作为akka actor启动。

计划部分:

private ActorRef myActor = Akka.system().actorOf( new Props(Retreiver.class)); @Override public void onStart(Application app) { log.info("Starting schedular.....!"); Akka.system() .scheduler() .schedule(Duration.create(0, TimeUnit.MILLISECONDS), Duration.create(30, TimeUnit.MINUTES), myActor, "tick", Akka.system().dispatcher()); } 

Retreiver类部分:

 public class Retreiver extends UntypedActor { private Logger.ALogger log = Logger.of(Retreiver .class); @Inject private myDataService dataService; @Override public void onReceive(Object arg0) throws Exception { if (0 != dataService.getDataCount()) { .... .... .... } 

}

我为dataService获取null。 请就此向我提出建议。

谢谢。

你得到了NullPointerException因为Akka正在实例化你的Retriever演员,而不是Guice。 您需要让Guice构建您的实例,然后将其传递给Akka, IndirectActorProducer可以帮助您实现此目的,例如:

 class RetrieverDependencyInjector implements IndirectActorProducer { final Injector injector; public RetrieverDependencyInjector(Injector injector) { this.injector = injector; } @Override public Class actorClass() { return Retriever.class; } @Override public Retriever produce() { return injector.getInstance(Retriever.class); } } 

请注意,每次调用时, produce() 必须创建一个新的Actor实例,它不能返回相同的实例。

然后,您可以通过RetrieverDependencyInjector获取Akka以检索您的actor,例如:

 ActorRef myActor = Akka.system().actorOf( Props.create(RetrieverDependencyInjector.class, injector) ); 

UPDATE

我想你进一步评论,你可以通过提供你想要的Actor作为构造函数参数的类来将RetrieverDependencyInjector变成GenericDependencyInjector ,这可能会让你做类似的事情:

 Props.create(GenericDependencyInjector.class, injector, Retriever.class) 

我没试过这个,但它可能会给你一个起点。

对于任何需要这个的人:

 public class GuiceInjectedActor implements IndirectActorProducer { final Injector injector; final Class actorClass; public GuiceInjectedActor(Injector injector, Class actorClass) { this.injector = injector; this.actorClass = actorClass; } @Override public Class actorClass() { return actorClass; } @Override public Actor produce() { return injector.getInstance(actorClass); } 

}

 Akka.system().actorOf(Props.create(GuiceInjectedActor.class, INJECTOR,Retreiver.class)) 

而已…!!!

可以有其他方法,例如,您可以在Boot或Some-Injector-Holder-class中放置静态注入器句柄,并在通过调用inheritance的方法创建actor时注入:preStart()

 public class Retreiver extends UntypedActor { private Logger.ALogger log = Logger.of(Retreiver .class); @Override public void preStart () { super.preStart (); Boot.injector.injectMembers (this); //Some-Injector-holder.injectMembers (this); } @Inject private myDataService dataService; @Override public void onReceive(Object arg0) throws Exception { if (0 != dataService.getDataCount()) { .... .... .... } } 

此外,您还可以在actor提供程序中注入注入器,以通过UntypedActorFactory范围内的注入器初始化actor:

 public class InjectingActorProvider implements Provider { @Inject private Injector injector; @SuppressWarnings("serial") @Override public final ActorRef get() { Props props = new Props(new UntypedActorFactory() { @Override public Actor create() { return injector.getInstance(actorClass); } }); props = props.withRouter(...); props = props.withDispatcher(...); actor = system.actorOf(props, actorName); return actor; } }