当我们已经了解Akka的基础知识之后,我们更多的是想知道在实际项目中,我们应该怎样使用起来。按照目前业界使用的技术来看,spring应该占主流,由于spring本身需要太多的配置文件,流程繁杂,这里采用较轻量的springboot来向大家介绍,只是省去诸多配置文件,操作过程都一样。
与springboot集成,是因为我们想把ActorSystem、Actor等组件的创建纳入SpringBoot容器中,方便管理。大家都知道,ActorSystem的创建不是依赖new方式,而是通过create方法,所以我们需要写一个Bean来生产ActorSystem。另外Actor,它也是通过actorOf()方法创建的,所以我们也需要写生产Actor引用的方法,Akka提供了IndirectActorProducer接口,通过实现该接口,我们就可以实现DI(依赖注入)。集成springboot之后,ActorSystem范围内的依赖都会交给SpringBoot来管理,并且每个ActorSystem都会持有一个ApplicationContext。
下面我们开始来看看集成是怎样实现的:
在实现之前,我们需要加入相关依赖,如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-slf4j_2.11</artifactId>
<version>2.5.16</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_2.11</artifactId>
<version>2.5.16</version>
</dependency>
第一步,实现IndirectActorProducer,用于生产Actor,既然是交给Spring管理,肯定少不了ApplicationContext对象和bean名称:
public class DIProducer implements IndirectActorProducer {
private ApplicationContext context;
private String beanName;
public DIProducer(ApplicationContext context,String beanName){
this.context=context;
this.beanName=beanName;
}
@Override
public Actor produce() {
return (Actor) context.getBean(beanName);
}
@Override
public Class<? extends Actor> actorClass() {
return (Class<? extends Actor>) context.getType(beanName);
}
}
第二步,实现了DI之后,我们就需要构造Props对象,用来创建ActorRef:
/**
* @author php
* @date 2018/12/16
* 扩展组件,ApplicationContext会在SpringBoot初始化的时候加载进来
* 构造Props,用于生产ActorRef
*/
public class SpringExt implements Extension {
private ApplicationContext context;
public void init(ApplicationContext context) {
System.out.println("applicationContext初始化...");
this.context = context;
}
/**
* 该方法用来创建Props对象,依赖前面创建的DI组件,获取到Props对象,我们就可以创建Actor bean对象
*
* @param beanName actor bean 名称
* @return props
*/
public Props create(String beanName) {
return Props.create(DIProducer.class, this.context, beanName);
}
}
第三步,创建SpringExtProvider继承AbstractExtensionId:
/**
* @author php
* @date 2018/12/16
* 通过继承AbstractExtensionId,我们可以在ActorSystem范围内创建并查找SpringExt
*/
public class SpringExtProvider extends AbstractExtensionId<SpringExt> {
private static SpringExtProvider provider = new SpringExtProvider();
public static SpringExtProvider getInstance() {
return provider;
}
@Override
public SpringExt createExtension(ExtendedActorSystem extendedActorSystem) {
return new SpringExt();
}
}
第四步,通过SpringExtProvider我们可以获取到SpringExt,通过SpringExt我们可以使用Props创建ActorRef对象,那么现在我们怎么来初始化ActorSystem,并扫描到纳入到容器的Actor呢?我们可以通过@Configuration来创建一个配置类:
/**
* @author php
* @date 2018/12/16
* 创建ActorSystem,并将其放入到spring管理,初始化ApplicationContext
*/
@Configuration
public class ScanConfig {
private final ApplicationContext context;
@Autowired
public ScanConfig(ApplicationContext context) {
this.context = context;
}
@Bean
public ActorSystem createSystem() {
ActorSystem system = ActorSystem.create("system");
SpringExtProvider.getInstance().get(system).init(context);
return system;
}
}
下面,我们就来创建一个Actor示例,来验证集成是否成功,如下:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TestActor extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder().matchAny(o -> {
System.out.println("接受到消息:" + o);
}).build();
}
}
特别注意,使用依赖注入框架时,Actor不能配置为单例的,否则程序会出现问题。这里我们简单输出接受到的消息。
测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class PackApplicationTests {
@Autowired
private ActorSystem actorSystem;
@Test
public void contextLoads() {
ActorRef ref = actorSystem.actorOf(SpringExtProvider.getInstance().get(actorSystem).create("testActor"), "testActor");
ref.tell("hello",ActorRef.noSender());
}
}
启动测试结果:
2018-12-16 21:23:03.405 INFO 24832 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@51549490: startup date [Sun Dec 16 21:23:03 SGT 2018]; root of context hierarchy
applicationContext初始化...
2018-12-16 21:23:04.900 INFO 24832 --- [ main] com.release.util.PackApplicationTests : Started PackApplicationTests in 2.052 seconds (JVM running for 3.141)
2018-12-16 21:23:04.947 INFO 24832 --- [ Thread-3] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@51549490: startup date [Sun Dec 16 21:23:03 SGT 2018]; root of context hierarchy
接受到消息:hello
大家可以清楚的看到,集成成功了,oh yeah.
手机扫一扫
移动阅读更方便
你可能感兴趣的文章