2016-04-13 19 views
5

私のプロジェクトでは、コードベースとしてLightbend activator templateを使用しました。それは完璧に動作しますが、例のActorはパラメータで作成されません。私は新しいアクターを作成して、などの建設中に、それにパラメータを渡す必要がJava Akka Actor with Spring with

このユースケースで
getContext().actorOf(SpringExtProvider.get(actorSystem).props("ControllerActor",type), "controller_" + type) 

、コントローラは、タイプparemeter小道具を使用して作成することができるようにする必要がありこれはコントローラを入力するために使用されます(明らかに)。各アクターは、オブジェクトのタイプに応じてオブジェクトの特定のキングを処理して制御するための特別な設計です。

しかし、このパラメータを渡すためにpropsメソッドに新しいパラメータを追加することはできません。それは動作していません。

これは私のコードです:

SpringExtension.java

package com.orange.spectre.core.akka.configuration; 

import akka.actor.AbstractExtensionId; 
import akka.actor.ExtendedActorSystem; 
import akka.actor.Extension; 
import akka.actor.Props; 
import com.orange.spectre.core.config.SpringActorProducer; 
import org.springframework.context.ApplicationContext; 

/** 
* Created by Hervé Darritchon on 04/04/2016. 
* <p> 
* An Akka Extension to provide access to Spring managed Actor Beans. 
*/ 
public class SpringExtension extends AbstractExtensionId<SpringExtension.SpringExt> { 

    /** 
    * The identifier used to access the SpringExtension. 
    */ 
    public static SpringExtension SpringExtProvider = new SpringExtension(); 

    /** 
    * Is used by Akka to instantiate the Extension identified by this 
    * ExtensionId, internal use only. 
    */ 
    @Override 
    public SpringExt createExtension(ExtendedActorSystem system) { 
     return new SpringExt(); 
    } 

    /** 
    * The Extension implementation. 
    */ 
    public static class SpringExt implements Extension { 

     private volatile ApplicationContext applicationContext; 

     /** 
     * Used to initialize the Spring application context for the extension. 
     * 
     * @param applicationContext 
     */ 
     public void initialize(ApplicationContext applicationContext) { 
      this.applicationContext = applicationContext; 
     } 

     /** 
     * Create a Props for the specified actorBeanName using the 
     * SpringActorProducer class. 
     * 
     * @param actorBeanName The name of the actor bean to create Props for 
     * @return a Props that will create the named actor bean using Spring 
     */ 
     public Props props(String actorBeanName) { 
      return Props.create(SpringActorProducer.class, 
        applicationContext, actorBeanName); 
     } 

     public Props props(String actorBeanName, String type) { 
      return Props.create(SpringActorProducer.class, 
        applicationContext, actorBeanName,type); 
     } 
    } 
} 

SpringActorProducer パッケージcom.orange.spectre.core.config。

import akka.actor.Actor; 
import akka.actor.IndirectActorProducer; 
import org.springframework.context.ApplicationContext; 

/** 
* Created by Hervé Darritchon on 21/03/2016. 
*/ 
public class SpringActorProducer implements IndirectActorProducer { 

    private final ApplicationContext applicationContext; 
    private final String actorBeanName; 
    private final String type; 

    public SpringActorProducer(ApplicationContext applicationContext, 
           String actorBeanName) { 
     this.applicationContext = applicationContext; 
     this.actorBeanName = actorBeanName; 
     this.type = null; 
    } 

    public SpringActorProducer(ApplicationContext applicationContext, 
           String actorBeanName, String type) { 
     this.applicationContext = applicationContext; 
     this.actorBeanName = actorBeanName; 
     this.type = type; 
    } 

    @Override 
    public Actor produce() { 
     return (Actor) applicationContext.getBean(actorBeanName); 
    } 

    @Override 
     public Class<? extends Actor> actorClass() { 
     return (Class<? extends Actor>) applicationContext.getType(actorBeanName); 
    } 
} 

それは(Documentation)のようにアッカと基本的に可能であると私は小道具のパラメータを持つ俳優を作成することはできません:あなたは私を助けることができる場合

public class DemoActor extends UntypedActor { 

    /** 
    * Create Props for an actor of this type. 
    * @param magicNumber The magic number to be passed to this actor’s constructor. 
    * @return a Props for creating this actor, which can then be further configured 
    *   (e.g. calling `.withDispatcher()` on it) 
    */ 
    public static Props props(final int magicNumber) { 
    return Props.create(new Creator<DemoActor>() { 
     private static final long serialVersionUID = 1L; 

     @Override 
     public DemoActor create() throws Exception { 
     return new DemoActor(magicNumber); 
     } 
    }); 
    } 

    final int magicNumber; 

    public DemoActor(int magicNumber) { 
    this.magicNumber = magicNumber; 
    } 

    @Override 
    public void onReceive(Object msg) { 
    // some behavior here 
    } 

} 

    system.actorOf(DemoActor.props(42), "demo"); 

すると、それは素晴らしいことです!

ありがとうございました。

+0

良い質問;あなたの努力が払うことを望みます! – GhostCat

+0

'SpringActorProducer'のコードを見直すと、コンストラクタは型パラメータを受け取り、それをプロパティに格納しますが、アクタを作成する' produce'メソッドはそれを使用しません。 – nickebbitt

+0

正直言って、あなたが試みていることが実際に可能かどうかは分かりません。アクターの作成をSpringコンテナに任せることで、あなたのアクターにオブジェクトを挿入するあなたのアプローチは、Springアプローチ、すなわち '@ Autowired'を使用しなければなりません。あなたの俳優に型を注入するのではなく、それぞれのオブジェクト型を扱うために複数の異なるアクターを定義しなければならない理由を、どの型のオブジェクトに通知するのですか?その後、オブジェクトを処理する正しいアクタにルーティングします – nickebbitt

答えて

2

私は "nickebbitt"と同意します。それがスポース可能であるかどうかはわかりません。そして1つの方法は、魔法の数ジェネレータの実装をアクタに注入することです。 さらに、私はIndirectActorProducer実装以下の提案するwouldlike:

public class SpringDIActor implements IndirectActorProducer { 

private static final Logger LOG = LoggerFactory.getLogger(SpringDIActor.class); 

private Class<? extends Actor> type; 
private Actor actorInstance = null; 

public SpringDIActor(Class<? extends Actor> type) { 
    this.type = type; 
} 

public SpringDIActor(Actor actorInstance) { 
    this.actorInstance = actorInstance; 
} 

/** 
* This factory method must produce a fresh actor instance upon each 
* invocation. <b>It is not permitted to return the same instance more than 
* once.</b> 
*/ 
@Override 
public Actor produce() { 
    Actor newActor = actorInstance; 
    actorInstance = null; 
    if (newActor == null) { 
     try { 
      newActor = type.newInstance(); 
     } catch (InstantiationException e) { 
      LOG.error("Unable to create actor of type:{}", type, e); 
     } catch (IllegalAccessException e) { 
      LOG.error("Unable to create actor of type:{}", type, e); 
     } 
    } 
    ApplicationContextProvider.getApplicationContext().getAutowireCapableBeanFactory().autowireBean(newActor); 
    return newActor; 
} 

/** 
* This method is used by [[Props]] to determine the type of actor which will 
* be created. This means that an instance of this `IndirectActorProducer` 
* will be created in order to call this method during any call to 
* [[Props#actorClass]]; it should be noted that such calls may 
* performed during actor set-up before the actual actor’s instantiation, and 
* that the instance created for calling `actorClass` is not necessarily reused 
* later to produce the actor. 
*/ 
@Override 
public Class<? extends Actor> actorClass() { 
    return type; 
}} 

これは次のようにあなたが共同任意のコードからSpringContextに直接accesingずに役者を作成することができます:

ActorSystem.create("system").actorOf(Props.create(SpringDIActor.class, DemoActor.class)) 

それからちょうどに@Autowiredアノテーションを使用しますデモアクター

DemoActorの注釈は不要です。