使用Akka時,Akka 所管理的對象是一堆的Actor,但我們不會所有的邏輯都會寫到Acotr裏,比如一些持久化的DAO的Service等而這些的Service是由Spring容器所管理的,然後想把這些spring所管理的Bean能自動注入到Actor裏實現過程參考官方的例子,需要定義兩個類分別實現ExtensionIdProvider接口與Extension接口
該方案是參考官方的擴展的例子結合自己理解弄出的方案,對比網上其他的方案所具有優點是Spring不會對Actor產生過多依賴,創建Actor還可以使用原生的actorOf方法來創建,而不是所有actor的創建都是使用Spring來創建,因爲很多情況下一個Actor不會像普通一個Spring Service Bean 那樣的生命週期,actor的生命很多可能是處理一個消息生成一個actor,處理完就會被銷燬。所以我的方案是Actor那個官方用法,通過擴展把拿到Spring容器的類來實現自動裝配
public class SpringContextHolderExtensionImpl implements Extension {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}
由上面的代碼看到這個擴展就是隻有一個ApplicationContext 字段保存Spring容器引用 。
public class SpringContextHolderExtension extends AbstractExtensionId<SpringContextHolderExtensionImpl> implements ExtensionIdProvider {
public static final SpringContextHolderExtension springContextHolderExtension = new SpringContextHolderExtension();
@Override
public SpringContextHolderExtensionImpl createExtension(ExtendedActorSystem extendedActorSystem) {
return new SpringContextHolderExtensionImpl();
}
@Override
public ExtensionId<? extends Extension> lookup() {
return springContextHolderExtension;
}
}
SpringContextHolderExtension 實現了ExtensionIdProvider 接口,顧名思義就是個Provider,當創建ActorSystem時就會調用其中createExtension方法來創建擴展實例,所以說每個擴展針對每個ActorSystem私有一個。
其中靜態類變量springContextHolderExtension 就是這個擴展的標識,可以通過這個標識來獲取到這個擴展
上面的兩個類是定義擴展
下面的兩個類是展示如何與Spring結合
AkkaConfig 這個類就是定義ActorSystemBean創建過程,在創建AcotorSystem後,就把ApplicationContext注入到擴展中
@Configuration
public class AkkaConfig {
@Autowired
private ApplicationContext applicationContext;
@Bean
public ActorSystem actorSystem() {
ActorSystem actorSystem = ActorSystem.create("herd-actor-system", akkaConfiguration());
springContextHolderExtension.get(actorSystem).setApplicationContext(applicationContext);
return actorSystem;
}
@Bean
public Config akkaConfiguration() {
return ConfigFactory.load();
}
}
public abstract class AbstractAutowiredBeanActor extends BaseActor {
@Override
public void preStart() throws Exception {
super.preStart();
ApplicationContext applicationContext = SpringContextHolderExtension.springContextHolderExtension.get(getContext().getSystem()).getApplicationContext();
try {
if (applicationContext != null) {
applicationContext.getAutowireCapableBeanFactory().autowireBean(this);
}
} catch (Exception e) {
log().error(e, e.getMessage());
}
}
}
定義AbstractAutowiredBeanActor,顧名思義它是個抽象類,重寫了Actor的preStart方法,從擴展裏取出了Spring容器然後爲actor進行自動裝配
applicationContext.getAutowireCapableBeanFactory().autowireBean(this);
需要用到Spring的管理的Bean就會直接繼承AbstractAutowiredBeanActor然後使用Spring'@Autowired'就可以自動注入例子如下
public class FooActor extends AbstractAutowiredBeanActor {
@Autowired
IRobotManager robotManager;
@Override
public Receive createReceive() {
return ReceiveBuilder.create()
.build();
}
}