Рубрики
Без рубрики

Введение в весну с Аккой

Быстрое и практичное руководство по использованию Акка с весной

Автор оригинала: baeldung.

1. Введение

В этой статье мы сосредоточимся на интеграции Akka с Spring Framework – чтобы позволить инъекции весенних услуг в актеров Акка.

Перед чтением этой статьи рекомендуется предварительное знание основ Акки.

Дальнейшее чтение:

Знакомство с актерами Акка на Яве

Путеводитель по Акка-Стримы

2. Инъекция зависимости в Акке

Акка является мощной рамкой приложения, основанной на модели concurrency Actor. Фреймвейт написан в Scala, что, конечно, делает его полностью годным к применению в Java-приложениях. И так очень часто мы хотим интегрировать Akka с существующим приложением на основе весны, которое или просто использовать весна для проводки бобов в актеров.

Проблема интеграции Весна/Акка заключается в разнице между управлением бобами весной и управлением актерами в Акке: актеры имеют определенный жизненный цикл, который отличается от типичного жизненного цикла весенних бобов .

Кроме того, актеры делятся на самого актера (что является внутренней деталью реализации и не может управляться Spring) и ссылку актера, которая доступна по коду клиента, а также сериализируемой и портативной между различными периодами выполнения Akka.

К счастью, Akka предоставляет механизм, а именно Акка расширения , что делает использование внешних структур впрыска зависимости довольно легкой задачей.

3. Maven зависимостей

Чтобы продемонстрировать использование Akka в нашем весеннем проекте, нам понадобится минимальная зависимость от весны – весенне-контекстный библиотеки, а также Акка-актер библиотека. Версии библиотеки могут быть извлечены в раздел пом :


    4.3.1.RELEASE
    2.4.8



    
        org.springframework
        spring-context
        ${spring.version}
    

    
        com.typesafe.akka
        akka-actor_2.11
        ${akka.version}
    

Убедитесь в том, чтобы проверить Maven Central для последних версий весенне-контекстный и Акка-актер Зависимости.

И заметьте, как, что Акка-актер зависимость имеет 2,11 postfix в своем названии, что означает, что эта версия фреймворка Akka была построена против версии Scala 2.11. Соответствующая версия библиотеки Scala будет временно включена в вашу сборку.

4. Инъекционные весенние бобы в Акка Актеры

Давайте создадим простое приложение Весна/Акка, состоящее из одного актера, который может ответить на имя человека, выдав приветствие этому человеку. Логика приветствия будет извлечена в отдельную службу. Мы хотим, чтобы autowire эту услугу актера экземпляра. Весенняя интеграция поможет нам в этой задаче.

4.1. Определение актера и службы

Чтобы продемонстрировать вливание службы в актера, мы создадим простой класс ПриветствиеАктор определяется как нетипийный актер (расширение UntypedActor базового класса). Основным методом каждого актера Акка является onReceive метод, который получает сообщение и обрабатывает его в соответствии с определенной логикой.

В нашем случае ПриветствиеАктор реализация проверяет, имеет ли сообщение предопределенный тип Приветствуйте , затем берет имя человека из Приветствуйте например, затем использует Поздравительная служба получить приветствие для этого человека и ответы отправителя с полученной строкой приветствия. Если сообщение имеет какой-либо другой неизвестный тип, оно передается в предопределенную неохвоженные метод.

Давайте посмотрим:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class GreetingActor extends UntypedActor {

    private GreetingService greetingService;

    // constructor

    @Override
    public void onReceive(Object message) throws Throwable {
        if (message instanceof Greet) {
            String name = ((Greet) message).getName();
            getSender().tell(greetingService.greet(name), getSelf());
        } else {
            unhandled(message);
        }
    }

    public static class Greet {

        private String name;

        // standard constructors/getters

    }
}

Обратите внимание, что Приветствуйте Тип сообщения определяется как статический внутренний класс внутри этого актера, который считается хорошей практикой. Принятые типы сообщений должны быть определены как можно ближе к актеру, чтобы избежать путаницы, на которых типы сообщений этот актер может обрабатывать.

Также обратите внимание на весенние аннотации @Component и @Scope – они определяют класс как весенний боб с прототип размах.

Область очень важна, потому что каждый запрос на поиск фасоли должен привести к недавно созданному экземпляру, так как это поведение соответствует жизненному циклу актера Акки. Если реализовать эту фасоль с некоторыми другими областями, типичный случай перезапуска субъектов в Akka, скорее всего, будет функционировать неправильно.

Наконец, обратите внимание, что мы не должны явно @Autowire Поздравительная служба пример – это возможно благодаря новой функции Весна 4.3 называется Неявная инъекция конструктора .

Осуществление GreeterService довольно просто, обратите внимание, что мы определили его как весной управляемых бобов, добавив @Component аннотация к нему (с однотонной области):

@Component
public class GreetingService {

    public String greet(String name) {
        return "Hello, " + name;
    }
}

4.2. Добавление весенней поддержки через расширение Akka

Самый простой способ интегрировать Spring с Akka – это расширение Akka.

Расширение – это однотонный экземпляр, созданный на одну актерную систему. Он состоит из самого класса расширения, который реализует интерфейс маркера Расширение , и расширение ID класса, который обычно наследует АннотацияЭкстензияИд .

Поскольку эти два класса тесно связаны между собой, имеет смысл реализовать Расширение класс, вложенный в РасширениеИд класс:

public class SpringExtension 
  extends AbstractExtensionId {

    public static final SpringExtension SPRING_EXTENSION_PROVIDER 
      = new SpringExtension();

    @Override
    public SpringExt createExtension(ExtendedActorSystem system) {
        return new SpringExt();
    }

    public static class SpringExt implements Extension {
        private volatile ApplicationContext applicationContext;

        public void initialize(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }

        public Props props(String actorBeanName) {
            return Props.create(
              SpringActorProducer.class, applicationContext, actorBeanName);
        }
    }
}

ПервыеВеснаЭкстензия реализует единый создатьЭкстензия метод из АннотацияЭкстензияИд класс – что объясняет создание экземпляра расширения, СпрингЭкст объект.

ВеснаЭкстензия класс также имеет статическое поле SPRING_EXTENSION_PROVIDER который содержит ссылку на его единственный экземпляр. Часто имеет смысл добавить частного конструктора, чтобы прямо заявить, что ВеснаЭкстенция должен быть однотонный класс, но мы опустить его для ясности.

Во-вторых , статический внутренний класс СпрингЭкст является само расширение. Как Расширение это просто интерфейс маркера, мы можем определить содержание этого класса, как мы считаем нужным.

В нашем случае нам понадобится инициализировать метод хранения весеннего ПриложениеКонтекст пример – этот метод будет называться только один раз за инициализацию расширения.

Кроме того, мы будем требовать реквизит метод создания Реквизиты объект. Реквизиты например, это план для актера, и в нашем случае Props.create метод получает SpringActorProducer аргументы класса и конструктора для этого класса. Это аргументы, с помощью которые будет называться конструктором этого класса.

реквизит метод будет выполняться каждый раз, когда нам понадобится ссылка на актера, управляемого Весной.

Третий и последняя часть головоломки является SpringActorProducer класс. Он реализует КосвенныйАкторПродюсер интерфейс, который позволяет переопределить процесс мгновенного висяния для актера путем реализации производить и актерКласс методика.

Как вы, наверное, уже догадались, вместо прямого мгновенного, он всегда будет получать актер экземпляр из весны в ПриложениеКонтекст . Как мы сделали актера прототип -Scoped фасоли, каждый звонок в производить метод вернет новый экземпляр актера:

public class SpringActorProducer implements IndirectActorProducer {

    private ApplicationContext applicationContext;

    private String beanActorName;

    public SpringActorProducer(ApplicationContext applicationContext, 
      String beanActorName) {
        this.applicationContext = applicationContext;
        this.beanActorName = beanActorName;
    }

    @Override
    public Actor produce() {
        return (Actor) applicationContext.getBean(beanActorName);
    }

    @Override
    public Class actorClass() {
        return (Class) applicationContext
          .getType(beanActorName);
    }
}

4.3. Сложив все вместе

Единственное, что осталось сделать, это создать класс конфигурации Spring (отмеченный аннотацией @Configuration ), который скажет Spring сканировать текущий пакет вместе со всеми вложенными пакетами (это обеспечивается аннотацией @ComponentScan ) и создать контейнер Spring.

Нам нужно только добавить одну дополнительную фасоль – АктерСистема экземпляр – и инициализировать весеннее расширение на этом АктерСистема :

@Configuration
@ComponentScan
public class AppConfiguration {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public ActorSystem actorSystem() {
        ActorSystem system = ActorSystem.create("akka-spring-demo");
        SPRING_EXTENSION_PROVIDER.get(system)
          .initialize(applicationContext);
        return system;
    }
}

4.4. Извлечение весенних проводных актеров

Чтобы проверить, что все работает правильно, мы можем ввести АктерСистема например, в нашем коде (или какой-нибудь код приложения, управляемый весной, или тест на основе весны) создайте Реквизиты объект для актера, используя наше расширение, получить ссылку на актера через Реквизиты объект и попытаться поприветствовать кого-то:

ActorRef greeter = system.actorOf(SPRING_EXTENSION_PROVIDER.get(system)
  .props("greetingActor"), "greeter");

FiniteDuration duration = FiniteDuration.create(1, TimeUnit.SECONDS);
Timeout timeout = Timeout.durationToTimeout(duration);

Future result = ask(greeter, new Greet("John"), timeout);

Assert.assertEquals("Hello, John", Await.result(result, duration));

Здесь мы используем типичную akka.pattern.Patterns.ask шаблон, который возвращает Будущие пример. Как только вычисление завершено, Будущие решается с значением, которое мы вернули в нашем ПриветствиеАктор.onMessasge метод.

Мы можем либо дождаться результата, применив решение Scala Await.result метод к Будущие , или, что более предпочтительно, построить все приложение с асинхронными узорами.

5. Заключение

В этой статье мы показали, как интегрировать Spring Framework с Akka и autowire бобов в актеров.

Исходный код статьи доступен для на GitHub .