Вступление
В 2024 году я начал изучать Spring AOP и решил проверять знания на практике - создал экспериментальный проект.
Идея была простой: что-то уникальное и реально полезное. На Java почти нет современных библиотек для интеграции с Python. Py4J и Jython либо ограничены, либо устарели, а полноценной интеграции с Spring Boot не было.
Так я решил создать библиотеку для связки Java и Python. Первоначально это был эксперимент с AOP и динамическим кодом, но в итоге проект вырос в полноценную open-source библиотеку, которую можно подключить одной зависимостью.
Начало эксперимента: изучение AOP в Spring Boot
Изначально проект под названием spring-python-executor позиционировался, как обычный пример моих навыков для резюме и ничего более. Поэтому к середине 2024 я быстро завершил разработку данного проекта. Он был написан на костылях, о какой либо безопасности или расширяемости в долгосрочной перспективе речи и не шло, но оно работало.
Первая версия проекта работала на шести аннотациях:
@PythonBeforeMethod
@PythonAfterMethod
@Py4JBeforeMethod
@Py4JAfterMethod
@SpelythonBeforeMethod
@SpelythonAfterMethod
@PythonBeforeMethod
и @PythonAfterMethod
работали с обычными скриптами, которые были независимы от Py4J или Spring Boot.
@Py4JBeforeMethod
и @Py4JAfterMethod
отвечали за использование Py4J вместе со скриптом указаным в методе.
@SpelythonBeforeMethod
и @SpelythonAfterMethod
были самым соком той версии. Эти две аннотации отвечали за Spelython или же по сути SpEL + Python. В каждом скрипте можно было использовать SpEL выражения.
И эту версию я решил выложить в Maven Central Repository по гайду на Ютубе, думая о том что эта версия проекта прокатит без должного тестирования.
P.S. Она не заработала, а забыл добавить spring.factories
Второй этап эксперимента: исправление и осознание
Вот мы и вернулись снова в 2025 и я решил полностью исправить своё резюме и проверить работоспособность моих проектов. Как вы уже догадались проект под названием spring-python-executor не оправдал ожиданий...
Я начал более углубленно изучать экосистему Spring Boot, а также как создавать свои Java проекты, которые не стыдно было бы разместить в Maven Central Repository.
После прочтения документации, я начал творить новое исправлять ошибки с прошлого. Ошибки в логике были максимально банальными и исправлялись в пару десяток минут, но глобальной проблемой было то, что проект было очень сложно расширять в случае нужды нового кода. А также исполнение скриптов через ProcessBuilder
- не самый лучший вариант.
Поэтому осознав все проблемы я пришёл к выводу, что нужно делить этот массивный кусок спагетти-кода на разные модули и добавить больше возможностей к исполнению скриптов, например, через REST или gRPC.
Но перед этим я создал ещё поддержку RestrictedPython и понял, что 6 аннотаций избыточно и нужно менять контракты между интерфейсами.
Финальный этап эксперимента: переход к production-ready коду
Переименовав проект в 'spring-boot-python-executor' и разделив эти проекты на разный модули (spring-boot-python-executor-common
, spring-boot-python-executor-core
, spring-boot-python-autoconfigure
, spring-boot-python-executor-starter
), я улучшил качество кода и расширяемости во много раз. Теперь не было болью рефакторить большие куски кода.
Дальнейшим шагом был рефакторинг кода в каждом модуле. Первым делом я пофиксил все контракты между интерфейсами и создал централизированный PythonProcessor
для исполнения Python скриптов и убрать избыточное количество аннотаций.
С этого момента имеются только четыре аннотации:
@PythonBefores
@PythonBefore
@PythonAfters
@PythonAfter
Аннотации с окончанием ...s служат для исполнения множества аннотаций без окончания, а также добавлено на этом этапе профилирование.
За Spelython или Py4J отвечает PythonResolverHolder
, которые содержит список с PythonResolver
с нужной реализацией.
За способ исполнения скриптов отвечает PythonExecutor
, который с этим этапом приобрел две реализации: GrpcPythonExecutor
и RestPythonExecutor
. Также создано два сервера на Python, задеплоиные в Docker Registry Hub: w4t3rcs/spring-boot-python-executor-python-grpc-server
, w4t3rcs/spring-boot-python-executor-python-rest-server
.
Вишенкой на торте стало добавления модулей отвечающих за кэширование и реализацию testcontainers.
Со всеми этими правками, общее состояние кода намного улучшилось и скорость разработки увеличилась в разы.
Примеры использования
Ниже предоставляю самые базовые примеры библиотеки в действии.
1. Простые аннотации
@PythonBefore("print('Before')")
@PythonAfter("print('After')")
public void doSomething() {
System.out.println("Hello from Java method");
}
2. Несколько скриптов (...s)
@PythonBefores({
@PythonBefore("print('Before 1')"),
@PythonBefore(script = "print('Before 2')", activeProfiles = "dev")
})
public void doSomething() {
System.out.println("Hello from Java method");
}
3. С помощью PythonProcessor
@Service
@RequiredArgsConstructor
public class ExampleService {
private final PythonProcessor processor;
public String getResult(String script) {
return processor.process(script, String.class).body();
}
}
Для более внушительного ознакомления с данной библиотекой, я рекомендую прочитать README.md и Javadoc'и с репозитория проекта.
Заключение
За год путь моего небольшого эксперимента превратился в полноценный open-source проект с гибкой архитектурой, поддержкой REST, gRPC и безопасного исполнения Python-скриптов. Сейчас spring-boot-python-executor
уже можно использовать в production, подключив всего одну зависимость.
Дальше я планирую расширять функционал, улучшать документацию, добавлять примеры реальных сценариев.
А теперь хочу спросить у вас:
Возвращались ли вы к своим незаконченным проектам с прошлого?
Приходилось ли вам интегрировать Python и Java в одном проекте?
Какой способ взаимодействия между ними для вас оказался самым удобным?
Интересна ли вам идея глубокой интеграции Python в экосистему Spring Boot?
Давайте обсудим это в комментариях! Буду рад обратной связи и вашим идеям по развитию проекта!
Комментарии (4)
pkokoshnikov
18.08.2025 15:36А graalpy чем не нравится? И причём тут spring? Кейсы применения непонятны. Такие аннотации обычно в коде руками реализовывают, если они действительно нужны.
w4t3rcs Автор
18.08.2025 15:36Я в ближайшее время хочу внедрить graalpy и jep в этот проект. А spring потому что все построено вокруг spring boot'a, тот же PythonProcessor это бин.
PqDn
Для питона как либы устанавливаются?
w4t3rcs Автор
Если через REST/gRPC сервер, то через PYTHON_ADDITIONAL_IMPORTS, если локально, то через pip. На гитхабе там полная инфа и о серверах и как их настраивать