AKKA 通過擴展實現與Spring集成

使用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();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章