看了java高并发编程,对akka的actor开发模式比较感兴趣,于是在日常一个开发任务中使用了下。
由于akka采用scala开发,对java开发者来说是黑盒。了解到akka在java里面最终是采用ForkJoinPool实现,相对于自己实现多线程并发,个人认为优势并不大。于是最终并未采用akka来实现功能。
现在将自己网上收集并跑起来的代码整理下,以便对此感兴趣的同学可以跑起来。
pom引用
注意scala和akka版本需要一致,这个我就吃了亏。
如akka-actor_2.12对应的scala需要 2.12.*版本,2.11类似。
<!-- akka -->
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-slf4j_2.12</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_2.12</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.12.3</version>
</dependency>
java类
akka spring运行环境配置。
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);
}
}
/**
* 扩展组件,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);
}
}
/**
* 通过继承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();
}
}
/**
* 创建ActorSystem,并将其放入到spring管理,初始化ApplicationContext
*/
@Configuration
public class AkkaConfig {
private final ApplicationContext context;
@Autowired
public AkkaConfig(ApplicationContext context) {
this.context = context;
}
@Bean
public ActorSystem actorSystem() {
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();
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebApplication.class)
public class AkkaApplicationTest {
@Autowired
private ActorSystem actorSystem;
@Test
public void testContextLoads() {
ActorRef ref = actorSystem.actorOf(SpringExtProvider.getInstance().get(actorSystem).create("testActor"), "testActor");
ref.tell("hello", ActorRef.noSender());
}
}