使用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 extends Actor> 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 extends Actor> actorClass; public GuiceInjectedActor(Injector injector, Class extends Actor> actorClass) { this.injector = injector; this.actorClass = actorClass; } @Override public Class extends Actor> 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; } }