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

 

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