Можно ли использовать Spring Boot с OSGi? Если нет, то планируете ли вы иметь OSGi Spring Boot?

Можно ли использовать Spring Boot с OSGi? Если нет, то планируете ли вы иметь OSGi Spring Boot (Apache Felix или Eclipse Equinox)? По моему мнению, облачные приложения должны быть очень модульными и обновляемыми, как это предлагает OSGi.

Ответ 1

Одной из возможностей является включение OSGi в ваше приложение загрузки Spring, чтобы некоторые части вашего приложения были доступны через фреймворк. См. fooobar.com/questions/244161/..., чтобы узнать, как вы можете запустить OSGi программно.

Но в целом нет ничего похожего на "OSGi-Support". OSGi можно интегрировать в каждое Java-приложение, и, наоборот, вы можете упаковать каждый Java-код (также ваше приложение Spring -Boot) в пакет OSGi, чтобы запустить его в контейнере OSGi (хотя, вероятно, он не будет имеют смысл вообще).

Ответ 2

На самом деле существует множество веских причин для развертывания Spring Boot в OSGi, главным из которых является производительность, особенно производительность при запуске, если ваша служба загрузки Spring - это функциональная служба (т.е. она запускается, возвращает результаты, заканчивается). Приложение, которое я сейчас тестирую в бета-тестировании в Spring Начало загрузки через ~ 0,5 секунды, развернутое в Equinox против 3,5 секунд. Другими причинами могут быть интеграция с OSGi-приложением или Java EE-сервером.

Тем не менее, вы также можете запустить OSGi из Spring Boot, по соображениям производительности я бы, скорее всего, одобрил Concierge как реализацию OSGi над Felix или Equinox, просто из-за его небольшого размера (если вашему приложению не нужны все функции более крупные реализации.

Другой альтернативой было бы обернуть библиотеки Spring, используемые вашим приложением Spring для загрузки в MSF4J (из WSO2). Это не займет много времени и может дать вам 10-кратный более быстрый запуск с 1/10-м использованием памяти.

Ответ 3

Да, есть возможность запускать приложения Spring Boot в контейнере OSGI.

Прежде всего, вам придется перейти от упаковки jar Spring Boot к bundle OSGI.

Если вы используете Maven вы можете использовать org.apache.felix:maven-bundle-plugin для этого. Как Spring Boot банки зависимостей не являются допустимыми OSGI расслоения, мы должны либо сделать их действительные связки с bnd инструмента или мы можем встроить их в сам пакет. Это можно сделать с помощью конфигурации maven-bundle-plugin, особенно с помощью <Embed-Dependency>.

Однако нам нужно как-то запустить пакет с приложением Spring Boot. Идея состоит в том, чтобы запустить Spring Boot в BundleActivator:

@Import(AppConfig.class)
@SpringBootConfiguration
@EnableAutoConfiguration
public class SpringBootBundleActivator implements BundleActivator {

    ConfigurableApplicationContext appContext;

    @Override
    public void start(BundleContext bundleContext) {
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        appContext = SpringApplication.run(SpringBootBundleActivator.class);
    }

    @Override
    public void stop(BundleContext bundleContext) {
        SpringApplication.exit(appContext, () -> 0);
    }
}

Вы также должны установить загрузчик классов контекста на загрузчик классов OSGI, загружающий пакет с помощью Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); , Это необходимо, потому что Spring использует контекстный загрузчик классов.

Вы можете увидеть это в действии в моем демо репо: https://github.com/StasKolodyuk/osgi-spring-boot-demo

Ответ 4

Spring boot - типичные приложения для весенней загрузки, немного "толстые" для osgi... если вы используете стартовую сеть или майку, вам нужно добавить какую-то схему определения порта, так как порты являются общими для всех osgi " services "система, на которой живет среда выполнения osgi.

Причина, по которой я бы порекомендовал избегать весенней загрузки, если вы не можете уменьшить ее, заключается в том, что созданная вами весенняя загрузочная фляга /war запускает загрузчик подкласса. Это не упрощает ситуацию, когда вы запутываетесь в стандартных проблемах загрузчика классов osgi (com.whwhat.someobject.MyClass не одинаковы в разных пакетах и загрузчиках классов, поскольку они не "импортируются" из одного пакета, который экспортируется во все остальные) если есть какие-либо требования к межсетевой связи.

Я бы посоветовал придерживаться следующих руководств, чтобы сократить "ядро весенней загрузки", если таковое существует, вам не нужен веб-прослушиватель и избегать всех межсетевых сервисных интерфейсов, которые используют любые объекты, которые не являются частью стандартного импорта (например, базовый Java се классы и т.д..). Вы заботитесь только о жизненном цикле, верно?

Ответ 5

Думаю, стоит публиковать отдельный ответ (не все читают все комментарии к ответам).

Отличное решение от @StasKolodyuk дает возможность запускать приложение Spring Boot в среде OSGI.

Но с ограничением: автоматическое сопоставление Spring Boot по аннотациям не работает из-за отсутствия поддержки сканирования пакетов при запуске в OSGI.

Вот еще один трюк, который наконец позволяет приложению Spring Boot с компонентами автоматически извлекаться из вашего кода для запуска в OSGI (я тестировал в Karaf).

Функциональный пример доступен по адресу https://github.com/dimmik/osgi-spring-boot-demo.

Хитрость заключается в предоставлении соответствующего ResourcePatternResolver экземпляру SpringApplication:

package by.kolodyuk.osgi.springboot;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.osgi.io.OsgiBundleResourcePatternResolver;

@SpringBootApplication
public class SpringBootBundleActivator implements BundleActivator {

    ConfigurableApplicationContext appContext;

    @Override
    public void start(BundleContext bundleContext) {
        // Set context classloader (main trick, to enable SpringBoot start at the first place)
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        // trick to enable scan: get osgi resource pattern resolver
        OsgiBundleResourcePatternResolver resourceResolver = new OsgiBundleResourcePatternResolver(bundleContext.getBundle());
        // and provide it to spring application
        appContext = new SpringApplication(resourceResolver, SpringBootBundleActivator.class).run();
    }

    @Override
    public void stop(BundleContext bundleContext) {
        SpringApplication.exit(appContext, () -> 0);
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringBootBundleActivator.class);
    }
}

Ответ 6

Нет, он не поддерживает OSGi. Spring Загрузка предназначена для создания микросервисов в виде упакованных приложений со всеми зависимостями и даже с контейнерами сервлетов, упакованными в исполняемый JAR, поэтому он очень модульный и обновляемый, без необходимости предоставления и настройки контейнера OSGi.