2016-04-13 21 views
5

Trong dự án của tôi, tôi đã sử dụng làm cơ sở mã số Lightbend activator template. Nó hoạt động hoàn hảo nhưng các diễn viên trong ví dụ không được tạo ra với các thông số.Các diễn viên Java Akka có tham số với Spring

tôi cần phải tạo ra một diễn viên mới và chuyển cho nó một tham số trong quá trình thi như:

getContext().actorOf(SpringExtProvider.get(actorSystem).props("ControllerActor",type), "controller_" + type) 

Trong trường hợp sử dụng này, bộ điều khiển cần để có thể được tạo ra với một đạo cụ paremeter loại được sử dụng để đánh máy (rõ ràng) là bộ điều khiển. Mỗi diễn viên được thiết kế đặc biệt để xử lý và kiểm soát một vị vua cụ thể của đối tượng tùy thuộc vào loại hình của nó.

Nhưng tôi không thể thêm tham số mới trong phương thức đạo cụ để chuyển thông số này. Nó không làm việc.

Đây là mã của tôi:

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 gói 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); 
    } 
} 

tôi không thể tạo một diễn viên với một tham số đạo cụ vì nó có thể về cơ bản với Akka như (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"); 

Nếu bạn có thể giúp tôi, nó phải là tuyệt vời!

Cảm ơn.

+0

Câu hỏi hay; hy vọng những nỗ lực của bạn sẽ trả hết! – GhostCat

+0

Nếu bạn xem lại mã trong 'SpringActorProducer', hàm tạo chấp nhận tham số kiểu và lưu trữ nó trong thuộc tính nhưng sau đó phương thức' produce' tạo ra tác nhân không sử dụng nó. – nickebbitt

+0

Thành thật mà nói, tôi không chắc chắn nếu những gì bạn đang cố gắng thực sự có thể. Bằng cách ủy quyền việc tạo diễn viên cho vùng chứa Spring, kinh nghiệm của tôi là cách tiếp cận của bạn để tiêm các đối tượng vào diễn viên của bạn phải sử dụng phương thức Spring, tức là '@ Autowired'. Thay vì tiêm loại vào diễn viên của bạn để thông báo cho nó loại đối tượng nào nó có thể xử lý tại sao không định nghĩa các tác nhân khác nhau để xử lý từng loại đối tượng cụ thể? Sau đó, bạn định tuyến đối tượng của mình đến đúng diễn viên để được xử lý – nickebbitt

Trả lời

2

Tôi đồng ý với "nickebbitt". Không chắc chắn rằng nó là không thể. Và một trong những cách là để tiêm một thực hiện các máy phát điện số ma thuật vào diễn viên. Hơn nữa, tôi wouldlike gợi ý sau đây thực hiện IndirectActorProducer:

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; 
}} 

này cho phép bạn đồng tạo diễn viên mà không cần trực tiếp đến accesing SpringContext từ bất kỳ mã như sau:

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

Sau đó chỉ cần sử dụng chú thích @Autowired vào DemoActor.

Không yêu cầu chú thích bổ sung trên DemoActor.

Các vấn đề liên quan