Первая проблема, что при доработке старого приложения по "устаревшим технологиям", надо как-то все подключить "по старому", т.е. не будет использовано удобного конструктора проектов Spring или Maven`а.
Spring приложение строится на аннотациях и бинах, что в свою очередь дает возможность просто подбросить в проект jar файл и весь его функционал автоматом подцепится, что также и создает проблему, если мы не подкинули нужную библиотеку/фреймворк, то не понятно по чему нужное нам не работает, т.к. ошибок нету от слова совсем... Сам запуск Spring boot, конечно - это инициализация конкретных классов, а потому тут понятно, что необходимо первоначально подключить. В конце я напишу какой именно список библиотек у меня сформировался, но главное понять как это все стартануть так, чтобы понять чего не хватает. Так же есть одна проблема, по которой я так и не нашел решения в сети, что и послужило причиной этой инструкции.
Минимальный набор у меня (но это не точно) сформировался такой (версии на текущий момент):
Код: Выделить всё
spring-aop-6.0.13.jar
spring-beans-6.0.13.jar
spring-boot-3.1.5.jar
spring-boot-autoconfigure-3.1.5.jar
spring-context-6.0.13.jar
spring-core-6.0.13.jar
spring-expression-6.0.13.jar
Тут основные либы, просто стартануть и если у них есть зависимости, то они должны об этом сказать (вроде).
точно понадобятся еще
Код: Выделить всё
slf4j-api-2.0.9.jar
slf4j-nop-2.0.7.jar
и
log4j-1.2.17.jar
log4j-api-2.21.1.jar
log4j-core-2.21.1.jar
еще, не помню когда, но потребовалась еще такая зависимость:
Код: Выделить всё
micrometer-commons-1.11.5.jar
micrometer-observation-1.11.5.jar
Но у нас задача использовать FeignClient, а для него тянутся еще куча зависимостей:
Код: Выделить всё
spring-cloud-commons-4.0.4.jar
spring-cloud-context-4.0.4.jar
spring-cloud-openfeign-core-4.0.4.jar
и
feign-core-12.4.jar
feign-form-3.8.0.jar
feign-form-spring-3.8.0.jar
feign-slf4j-12.4.jar
Т.к. мне нужен Rest, то до кучи еще:
Код: Выделить всё
jackson-annotations-2.15.3.jar
jackson-core-2.15.3.jar
jackson-databind-2.15.3.jar
А для удобства:
Чтобы начать - этого должно хватить...
Так вот, чтобы стартануть Spring, в Main процедуре выполняется команда Run для SpringBoot (не буду давать инструкцию, т.к. этого добра навалом...)
Но такой запуск, не даст ошибок по зависимостям, потому для первых попыток рекомендую использовать запуск через создание руками объекта ApplicationContext и получение от туда бинов (это все есть в начальных уроках по Spring). Такой запуск заставляет систему сканировать, так сказать, систему в ручном режиме, тянуть нужные зависимости, и вызовать исключения о не найденных зависимостях, в то время как запуск Run, просто игнорирует часть зависимостей, про которые ничего не знает. В принципе, если включить DEBUG в настройках Логера (кстати, его необходимо обязательно настроить, иначе не запустится), то в логах будет информация о Бинах, которые нашел и которых НЕ нашел.
Log4j в моем приложении ранее использовался, потому его особо не настраивал, но запуск Spring должен осуществляется строго после инициализации log4j.
Перед главным классом ставим аннотации:
Код: Выделить всё
@SpringBootApplication
@EnableFeignClients
@EnableScheduling
public class MainApps {
...
}
Первая обязательная, далее включаются необходимые функции, которые не будут работать без этих аннотаций (EnableScheduling - по данной я ничего не писал, там все понятно итак).
Стартуем в главной функции наше приложение так:
Код: Выделить всё
String finalSettingsPatch = SettingsPatch; //Если вам не надо настраивать как-то особо какой либо класс при инициализации, то это строка как и все что с Config.class Вам не нужно
ApplicationContext contextMain = new SpringApplicationBuilder()
.bannerMode(Banner.Mode.OFF) //Отключаем баннер заставку SpingBoot, которая есть только при таком способе запуска через Run
.initializers((ApplicationContextInitializer<GenericApplicationContext>) context -> {
context.registerBean(Config.class, finalSettingsPatch); //Собственный класс конфига должен быть инициализирован первым и с параметрами, потому инициализируем его так...
})
.sources(MainApps.class)
.run(args);
Config cfg = (Config) contextMain.getBean("ru.myApp.cfg.Config"); // интересно, что бинов "Config.class" несколько, потому указать надо явно
LOGGER.debug(cfg.toString()); // Проверяем то ли нашли.
Config.class - это исторический класс в моем старом приложении, что отвечает за настройки этого приложения, для работы Spring он не нужен, просто пример. Из строк Builder можно исключить любую, кроме run - это не повлияет на запуск, разве что без sources он может не найти ничего из текущего проекта (хз как так), но вместо sources можно использовать соответствующую аннотацию, см. любой учебник по Spring.
Заметим, что мой Конфиг, для корректной работы исходного приложения, инициализироваться должен один раз, и, несмотря на вызов конструкции registerBean с параметрами, getBean вызывается без параметров, но getBean найдет, инициализированый ранее объект, собственно как везде, где он будет нужен.
У класса Config есть только один конструктор с параметром, а автоматически Spring пытается создать Бин через конструктор Без параметров, потому перед классом Config нужны аннотации:
Где Lazy запрещает Spring`у самостоятельно инициализировать Бин при старте, до того момента, пока он не понадобится. Мы его инициализируем сами с параметром, а т.к. Spring делает только один его экземпляр, то далее проблем с его использованием не возникает.
Если необходимо использовать Бины, которые должны каждый раз создаваться новые, то перед классом надо поставить такой набор аннотаций:
Lazy тут нужен, чтобы Spring не создавал его при запуске, ну хотя бы потому, что он не нужен и никогда использоваться этот экземпляр не будет, а Scope с именем prototype как раз заставляет каждый раз создавать новый объект, при использовании getBean или @Autowired.
Лично я тут искал и проверял еще один момент, о котором при этом обычно не говорят. в Scope по умолчанию singleton (его указвать не надо) Spring берет на себя контроль за объектомв в памяти, а вот в случае prototype Spring только создает данный объект и забывает про его существование, потому далее его существование контролируется только Java и когда он не будет никому нужен, он будет автоматически уничтожен, т.е. удален из памяти как и любой класс Java, созданный оператором new. Фактически просто вместо new мы используем теперь getBean или @Autowired, но получившийся объект тепь получит все возможности Spring, т.е. в нем можно теперь использовать @Autowired и другие плюшки, иначе, для использования того же FeignClient, придется в класс как-то передать AplicationContext, т.к. FeignClient можно вытянуть только от туда, если он объявлен как interface и без proxy обертки от Spring, просто работать не будет.
Далее можно создавать класс с аннотацией @FeignClient и всего что рядом с ним и настраивать клиент, далее все по инструкции из учебников или на форумах или в др. инструкциях в сети.