6

我在作为 akka 演员启动的服务器的字段注入上遇到空指针异常。

计划部分:

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

}

检索器类部分:

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()) {
    ....
    ....
    ....
    }

}

我的数据服务为空。请就此给我建议。

谢谢。

4

3 回答 3

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

就是这样...!!!

于 2013-07-16T18:40:28.493 回答
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变成一个,这可能会让你做类似的事情:GenericDependencyInjectorActor

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

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

于 2013-07-12T10:14:55.107 回答
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;
    }
}
于 2013-08-05T08:48:25.160 回答