Custom Kafka Deserializer и Spring’овый контекст. Как инжектить в статические поля
Привет, меня зовут Николай Пискунов, я ведущий разработчик в подразделении Big Data. Мы в beeline cloud регулярно сталкиваемся с задачами, требующими кастомных решений, поэтому сегодня расскажу, как инжектить в статические поля. Как всегда — на примерах. Поехали.
На практике десериализаторов, представленных в ядре Spring, хватает в 99% случаев. Но бывают ситуации, когда всё же требуется описать свою логику предобработки входящего сообщения.
Для наглядности предлагаю рассмотреть гипотетический случай, когда на вход Kafka подается строка лога с задаваемым разделителем. В этой строке нас интересует лишь часть сообщения: мы будем делить строку по определенному символу и собирать из получившегося массива новую строку.
Задавать разделитель и индексы в файле application.properties мы планируем так:
Сразу скажу, что org.apache.kafka.common.serialization.Deserializer и все его реализации не знают о спринговом контексте ничего — от слова совсем. Даже если попытаться сделать из него бин, пометив соответствующей аннотацией, например @Component.
Для этого напишем сам Deserializer и попробуем прямо в него заинжектить требуемые настройки, используя спринговую аннотацию @Value:
К сожалению, нам вернется null при попытке получить значения:
А если мы проставим стандартные значения в @Values, результат будет таким же:
@Value("${kafka.message.deserializer.delimiter:,}")
Но можно использовать статические поля, описав их в соседнем классе. Вот только надо придумать, как в них заинжектить данные из спрингового контекста. Конечно, это должен быть спринговый бин, например @Component, и в нем мы определим статические поля, включая поля, которые будут заполняться данными из properties:
Теперь напишем сеттеры, они-то и будут присваивать значения статическим полям:
Важно помнить, что @Values необходимо навешивать над методами, иначе не заработает. И, если вы решите обновить контекст без перезапуска приложения, например, поправив значения в файле конфигураций, обновятся и статические поля.
Теперь перепишем сам десериалайзер:
А вот теперь мы можем конфигурировать Deserializer, используя спринговый контекст:
У такого подхода есть свои минусы. По факту у нас дублируются данные в хипе, которые не удалит GC ввиду того, что первые хранятся в контексте спринга, вторые — в статических полях. Поэтому старайтесь инжектить конкретные бины и не делайте так:
beeline cloud — secure cloud provider.
Разрабатываем облачные решения, чтобы вы предоставляли клиентам лучшие сервисы.