spring boot集成akka

由于Akka的Actor在初始化的时候必须使用System或者Context的工厂方法actorOf创建新的Actor实例,不能使用构造器来初始化,而使用Spring的Service或者Component注解,会导致使用构造器初始化Actor,所以会抛出以下异常:

akka.actor.ActorInitializationException: You cannot create an instance of [com.jikuan.zjk.akka.actor.TestActor] 
explicitly using the constructor (new). You have to use one of the 'actorOf' factory methods to create a new actor. 
See the documentation.  


真正想用注解方式加载akka类其实用处不大,最大的是想在akka actor类中加载写的其他的service时候,无法使用注解,但是你的service又都是注解写的,这个就比较恶心,所以还是要想办法将akka集成,这样就可以像使用spring一样使用akka了,下面是具体的做法: 参考:https://www.linkedin.com/pulse/spring-boot-akka-part-1-aliaksandr-liakh

1.构建SpringActorProducer类

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

/*
 * jikuan.zjk
 */

public class SpringActorProducer implements IndirectActorProducer {

  final private ApplicationContext applicationContext;
  final private String actorBeanName;

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

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

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

2.构建SpringExtension类

package com.alibaba.dbtech.paas.app.adha.akka;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import akka.actor.Extension;
import akka.actor.Props;

/*
 * jikuan.zjk
 */
@Component("springExtension")  
public class SpringExtension implements Extension {
  private ApplicationContext applicationContext;

  public void initialize(ApplicationContext applicationContext) {
      this.applicationContext = applicationContext;
  }

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

3.创建bean 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;

import akka.actor.ActorSystem;

/*
 * jikuan.zjk
 */

@Configuration
public class AkkaConfig {

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private SpringExtension springExtension;

    @Bean
    public ActorSystem actorSystem() {
        ActorSystem actorSystem = ActorSystem.create("ActorSystem");
        springExtension.initialize(applicationContext);
        return actorSystem;
    }

    @Bean
    public Config akkaConfiguration() {
        return ConfigFactory.load();
    }
}

4.创建actor   

@Autowired
  AdhaHeartbeatService adhaHeartbeatService;
可以直接像上面那样加载自己的service了

@Autowired
  private ActorSystem actorSystem;
  @Autowired
  private SpringExtension springExtension;
像spring一样加载ActorSystem

ActorRef routerActorRef =
        actorSystem.actorOf(springExtension.props("detectActor2").withDispatcher("detect-dispatcher")
            .withRouter(new SmallestMailboxPool(50000)), "detectRouterActor");
创建actor方式如上,上面是项目中使用独立Dispatcher和router的例子,简单的使用可以使用下面的创建方式

ActorRef routerActorRef =
        actorSystem.actorOf(springExtension.props("detectActor2"), "detectRouterActor");
其中detectActor2是你在DetectActor2 Actor上使用 @Component("detectActor2") 对应

下面是详细代码:

/*
 * AdhaDetect class, single thread task jikuan.zjk
 */
@RestController
public class AdhaAkkaDetect2 extends Detect {
  @Autowired
  AdhaHeartbeatService adhaHeartbeatService;
  @Autowired
  AdhaMetaTask adhaMetaTask;
  @Autowired
  private ActorSystem actorSystem;
  @Autowired
  private SpringExtension springExtension;

  public void detect(String detectStatus, int detectCount) {
    
    ActorRef routerActorRef =
        actorSystem.actorOf(springExtension.props("detectActor2").withDispatcher("detect-dispatcher")
            .withRouter(new SmallestMailboxPool(50000)), "detectRouterActor");
    
    System.out.println("into detect function,resultActorRef=" + resultActorRef.path());

    
    routerActorRef.tell(new MapMessage(instance, connectMap), ActorRef.noSender());
  }
}



下面是DetectActor2代码

@Component("detectActor2")
@Scope("prototype")
public class DetectActor2 extends AbstractActor {

  public PartialFunction receive() {
    return ReceiveBuilder.match(String.class, s -> {
      
      System.out.printf("get %s\n" , s);
      sender().tell("Hi", self());
      
    }).matchAny(x -> {
      System.out.printf("I dont know what you see in DetectActor,%s", getContext().self().path());
      sender().tell(new Status.Failure(new Exception("I dont know what you see")), self());
    }).build();
  }

  public static Props props(String response) {
    return Props.create(DetectActor2.class, response);
  }
}





  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值