Недавно мы пытались реализовать планировщик (Кварц) с одним из наших микросервисов.

Поскольку микросервис был написан на Clojure, перед нами стояла задача реализовать интерфейсы кварцевого планировщика, которые в основном написаны на Java.

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

Итак, мы решили заняться реализацией Java.

Таким образом, мы столкнулись с проблемой реализации интерфейсов, заданных в Java, с помощью кварцевого планировщика в Clojure.

В Интернете нашел различные методы реализации интерфейсов, которые предоставляет Clojure.

Во-первых, позвольте мне пролить свет на кварцевый планировщик и предоставляемые им интерфейсы. Quartz имеет понятие Job (содержащее информацию о задании, т.е. какой класс должен быть выполнен и метаданные) и Triggers (время, в которое оно должно быть запущено, т.е. время запуска и задание, которое выполняется).

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

Теперь, когда вы немного поняли, что нам нужно реализовать интерфейс java и метод (выполнить).

Clojure предоставляет вам четыре способа реализации или расширения класса java, которые подробно обсуждаются.

доверенное лицо

Вот небольшая реализация метода execute из интерфейса Job.

Чтобы вызвать функцию выполнения на объекте:

(.execute  proxy-class-object nil)

Плюсы использования прокси:

  1. Никакой предварительной компиляции не требуется

Минусы:

  1. Предоставляет вам объект прокси-класса, то есть анонимный, который недолговечен.
  2. Может реализовывать только те методы, которые присутствуют в интерфейсе.

ген-класс

Вот небольшая реализация метода execute из интерфейса Job.

Еще одна вещь: gen-class требует предварительной компиляции. Итак, вы должны включить функцию : aot для этого пространства имен в конфигурации вашего проекта.

Чтобы вызвать функцию выполнения на объекте:

(.execute gen-class-object nil)                           (.customMethod gen-class-object "Hello World From Extra Method in gen-class")

Основное различие, которое вы обнаружите, - это типы объектов, которые создают оба подхода.

Плюсы использования gen-class:

  1. Создает именованные объекты
  2. Может создавать методы, которых нет в интерфейсе, т.е. помогает увеличить мощность интерфейса.

Минусы:

  1. Требования заблаговременно Компиляция

овеществлять

(.execute reify-class-object nil)

Reify не требует предварительной компиляции.

Reify и Proxy во многом похожи по своему поведению.

Есть некоторые отличия, такие как:

  1. Нет поддержки методов суперкласса, мы можем использовать proxy-super в определении прокси-класса для вызова методов суперкласса.
  2. Остальные отличия перечислены здесь.

Наши проблемы с подходами

proxy и reify были для нас функционально одинаковыми (нам не требовался вызов методов суперкласса). Но поскольку оба эти подхода создают анонимный класс, мы не смогли сослаться на него. Принимая во внимание, что gen-class предоставляет нам именованные объекты класса.

Счастливого Clojure !!