我在服务器的字段注入时获得空指针异常,该服务器以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。请告诉我这个。
感谢。
答案 0 :(得分:8)
对于任何需要此功能的人:
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))
多数民众赞成...... !!!
答案 1 :(得分:7)
你得到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
实例,它不能返回相同的实例。
然后,您可以让Akka通过RetrieverDependencyInjector
检索您的演员,例如:
ActorRef myActor = Akka.system().actorOf(
Props.create(RetrieverDependencyInjector.class, injector)
);
<强>更新强>
我考虑过你进一步评论,你可以通过提供你想要的RetrieverDependencyInjector
类作为构造函数参数来将GenericDependencyInjector
变成Actor
,这可能会允许你可以这样做:
Props.create(GenericDependencyInjector.class, injector, Retriever.class)
我没试过这个,但它可能会给你一个起点。
答案 2 :(得分:2)
可以有其他方法,例如,您可以在Boot或Some-Injector-Holder-class中放置静态注入器句柄,并在通过调用继承方法创建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<ActorRef> {
@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;
}
}