Как-то я засиделся на работе добавляя новую функциональность в один "небольшой"  и довольно старенький сервис написанный на Spring.  Редактируя очередной XML файл Spring конфигурации я подумал: а чего это в 21 веке мы всё еще не перевели наш проект на Java-based конфигурации и наши разработчики постоянно правят XML?  С этими мыслями и была закрыта крышка ноутбука в этот день... Вначале я попробовал решение в лоб: по-быстрому сконвертировать XML конфигурации в Java классы в текущей задаче.  Переведя с десяток бинов руками выходило, что на перевод одной конфигурации у меня уходит примерно час, а это значит что на перевод всего проекта уйдёт порядка недели. И еще есть большая вероятность человеческого фактора внесения ошибок: не туда скопировал, перепутал порядок полей и т. д, а это еще трата N времени на ровном месте.  Плюс проектов с XML у меня на самом деле еще и несколько и надо бы и их перевести. Собственно в этот момент и появилась идея автоматизировать конвертацию. Стало понятно, что тут нужна автоматическая конвертация. Была надежда, что уже есть что-то готовое и я быстро разберусь с этой проблемой, но оказалось что - нет. Тогда появилась идея написать свою утилиту. Но чтобы не погрязнуть в Spring (а за много лет там было написано столько всего, что ого-го) было сделано решено ввести на старте несколько ограничений: Конвертор не должен явно обращаться к классам проекта - это важное ограничение введено намерено чтобы не уйти во все тяжкие рефлексии и случайно не написать второй Spring. Исключения тут составляют Java конфигурации импортированные в XML. Чтение конфигураций с bean definitions должно быть аналогично чтению самого Spring -  теми же reader-ами - org.springframework.beans.factory.xml.XmlBeanDefinitionReader. Генерация конфигурации должна быть на базе собственной модели - чтобы был строгий контроль поддерживаемых описаний бинов. Конвертируются типовые бины, вся "экзотика" допереводится руками. В итоге схема работы утили получилась следующая: Часть из этого была известна заранее, часть нашлась по ходу дела - набралось много интересного про XML конфигурации Spring. Я просто обязан всем этим поделиться :-)  Spring допускает в XML конфигурация много вольностей и "трюков", самые интересные найденные много описаны ниже.  Пришлось реализовать рекурсивный обход описаний, как при проверке валидации бинов, так и в момент генераторе кода. Да, оказывается все новое у нас в проектах уже пишется на Java-конфигурациях и чтобы сконвертировать старое нужно уметь зачитать и новые конфигурации.  Тут на помощь пришел спринговый ConfigurationClassPostProcessor, который как раз умеет дочитать описание бинов объявленных в классах. В конверторе есть ключ для включения строгого режима, который проверяет, что все импорты присутствуют в classpath Довольно просто получилось добавить генерацию ArrayList и HashMap по коду.  Но остался не поддерживаемым случай, когда поле назначения типа массив, это спринг уже угадывает сам по коду проекта получая тип поля куда сеттятся Mergeable объекты. Этот случай получилось поддержать. В  момент генерации класса конфигурации переменные окружения добавляются полями с аннотациейorg.springframework.beans.factory.annotation.Value  Тут все не так однозначно, если с фабричным методом все понятно (т.к. класс бина описывается в XML), то поддержку AbstractFactoryBeanна полях сделать не удалось, поэтому бины с фабриками пропускаются и остаются жить в XML. Ну а чего б нет, и их довольно много даже у самого Spring (Например: http://www.springframework.org/schema/c, http://www.springframework.org/schema/p). XML конфигурации с такими xmlns не смогут корректно прочитаться, поэтому первую конвертацию следует делать с флагом -s что отловить и по возможности убрать кастомные xmlns. Привести String к int вообще мелочь, на самом деле даже можно  досоздавать объекты (например поле Resource со значение file:  - досоздаст объект класса FileSystemResource) Спокойно прожевывает конфигурацию, и создавая new FileSystemResource("my_file.txt") Этот случай уходит в ручную доконвертацию. Т.е. утилита выставит String значение в конструктор или seter, дальше нужно руками привести поле к нужному классу. Большие ребята могут себе позволить поддерживать свой EL. Я к сожалению не могу :) Бины с EL будут пропущены и останутся в XML. А вот это вообще киллер фича, которую лучше показать на примере: Допустим есть класс: И конфиг к нему Так вот, при отсутствии одного из параметра конструктора, Spring поищет бины с таким типом и если в контексте ровно один бин такого типа, то он его сам доавтовайрит и корректно создаст бин. Утилита конечно такое делать не умеет, т.к. не ходит в исходники проекта.  Это нужно будет поправить сами. В ходе конвертации наших проектов был найден ряд таких бинов и добавлены необходимые поля в ручную.  При сборке все XML конфигурации оказываются в ресурсах и Spring их найдет и корректно поднимет контекст. При это явный импорт одной  XML конфигурации в другую не требуется. Тут пришлось отказаться от перевода модулей одного репозитория по отдельности, а сделать сканирование всего проекта и создания общего описания бинов. И уже потом по этому общему описанию переводить конфигурации.  Имхо это большой минут, т.к. теряется понимание зон видимости. При переводе на Java конфигурацию стало видно какие классы/методы/модули на сам деле не приватные в проекте и утекли. К счастью у меня таких классов было немного. В результате получилась универсальная утилита, которая позволила перевести часть наших активно развивающихся сервисов в Java конфигурацию, что значительно повысило удовольствие работы с проектами. Какие плюсы конвертации можно выделить: Повышена комфортность собственной работы, а так уменьшение по времени на правки конфигов: начинают в полную силу работать плюшки IDE: рефакторинг, автодополнение, генерация кода и т.д. Повышена прозрачность конфигурации: нет неявной автоподстовновки, нет обращений к приватным классам, полям, классам Все зависимости между модулями теперь стали явными - теперь если один модуль требует бин другом модуля, эту зависимость требуется явного объявить в pom.xml/build.gradle модуля, что позволяет отлавливать некорректную связанность при написании кода или на ревью. Код и релизы находятся тут -  spring-xml-to-java-converter (лицензия MIT) Что уже сейчас поддерживается: Мультимодульные проекты. Неявные зависимости конфигураций. Автоматическое удаление сконвертированных бинов из XML конфигураций. Бины без "id". Параметризованные бины constructor-arg/property. Бины с переменными окружения. Вложенные бины. Бины с list/set. Бины с фабричным методом. Аттрибуты lazy, depend-on, init-method, destroy-method, scope, primary. Что НЕ поддерживается: Именованные параметры конструкторов полей. Абстрактные бины и бины с родителями. Бины с фабриками, когда не указан явно класс создаваемого фабрикой объекта. Бины с EL выражениями, либо со ссылкой на classpath. Бины со ссылкой на бин, который отсутствует в созданном BeanDefinitionRegistry. Подробная инструкция по работы с утилитой находится в readme репозитория. Мое лично мнение, что любой Spring-проект рано или поздно стоит перевести на Java-based конфигурацию, но хочется отметить несколько важных моментов. Когда стоит задуматься, а готов ли проект к переводу: Если проект плохо покрыт тестами или вы не готовы потратить время на регрессионное тестирование. Когда проект в архиве - не стоит переводить проект "на будущее" без релиза. Это может сыграть злую шутку, например когда нужно будет срочно выкатить hotfix. Когда в XML конфигурации много самописных xmlns расширений - это все придется сконвертировать руками. Когда проект является частью родительского проекта на XML - если в проект работает много команд следует заранее договорится о переводе своего модуля, чтобы все были готовы. Когда точно стоит переводить: Проект активно развивается и изменяется -  разработка станет сильно приятнее и эффективнее после конвертации. Спасибо что дочитали, надеюсь было полезно (⊙‿⊙).