Подтвердить что ты не робот

Проектирование библиотеки Java с помощью Spring

Я извлекаю некоторые функции из существующей программы в отдельную библиотеку. Эта программа использует Spring для инъекций зависимостей и других задач, и я также хотел бы использовать ее в библиотеке.

Эта библиотека должна контролировать файловую систему для изменений, поэтому для ее запуска будет создан какой-то отдельный поток.

Я не знаю, какие мои параметры предназначены для инициализации библиотеки:

  • Как инициализировать библиотечный контекст? Я не могу предположить, что пользователи библиотеки также будут использовать Spring, но я могу распространять Spring с помощью библиотеки.

  • Как мне управлять потоком мониторинга файловой системы? Является ли хорошим дизайном ожидать, что программа создаст основной класс библиотеки и инициирует вызов или что-то в этом роде?

4b9b3361

Ответ 1

Как инициализировать библиотечный контекст? Я не могу предположить, что пользователи библиотеки также будут использовать Spring, но я могу распространять Spring с помощью библиотеки.

Это для вашей библиотеки, чтобы создать Spring способ, которым это необходимо. Обычно это делается в вашей входной точке интерфейса, которая делегирует процедуру, например, ClassPathXmlApplicationContext для настройки spring. Образец может быть

public class SpringContextLoader {
   private static ApplicationContext ctx = null;
   public static void init() {
       if (ctx == null) {
          ctx = ClassPathXmlApplicationContext("classpath:/applicatonContext.xml");
       }
   }
}

Как мне управлять потоком мониторинга файловой системы? Является ли хорошим дизайном ожидать, что программа создаст основной класс библиотеки и инициирует вызов или что-то в этом роде?

В этом случае вы, вероятно, будете предоставлять поток не-демона, например поток, который должен быть завершен вручную, чтобы приложение могло выйти из него чисто. Следовательно, вы должны предоставить механизмы start и stop. В вашем случае их, вероятно, лучше называть registerEventListener и unregisterAllEventListener (поскольку я предполагаю, что вы хотите передать события файловой системы клиенту...). Другой альтернативой может быть использование quartz планирования с помощью spring.

Ответ 2

Как инициализировать библиотечный контекст? Я не могу предположить, что пользователи библиотеки также будут использовать Spring, но я могу распространять Springс библиотекой.

Я пишу библиотеку, используя контекст Spring, и я сделал что-то подобное, предполагая, что ваша библиотека называется FooLib, имеет две службы с именем FooService и BarService и класс SpringContext, который настраивает ваш контекст Spring через java config:

public final class FooLib {

    private static ApplicationContext applicationContext;

    private FooLib() {
    }

    public static FooService getFooService() {
        return getApplicationContext().getBean(FooService.class);
    }

    public static BarService getBarService() {
        return getApplicationContext().getBean(BarService.class);
    }

    private static ApplicationContext getApplicationContext() {
        if (applicationContext == null) {
            applicationContext = new AnnotationConfigApplicationContext(SpringContext.class);
        }
        return applicationContext;
    }
}

Тогда клиент может использовать BarService следующим образом:

BarService barService = FooLib.getBarService();

Как мне управлять потоком мониторинга файловой системы? Хороший дизайн ожидайте, что программа создаст основной класс библиотеки и вызвать init или что-то в этом роде?

Вы можете запустить свою подсистему мониторинга статически в контексте Spring внутри класса SpringContext, например.

@Configuration
@ComponentScan(basePackages = "com.yourgroupid.foolib")
public class SpringContext {

    @Bean
    public MonitoringSystem monitoringSystem() {
        MonitoringSystem monitoringSystem = new MonitoringSystem();
        monitoringSystem.start();
        return monitoringSystem;
    }

}

Этого должно быть достаточно, потому что Spring по умолчанию создает свой beans.

Приветствия

Ответ 3

Как инициализировать библиотечный контекст? Я не могу предположить, что пользователи библиотеки также будут использовать Spring, но я могу распространять Spring с помощью библиотеки.

Вы можете использовать PropertyPlaceholderConfigurer для чтения настроек конфигурации из (возможно, внешнего) файла свойств, который может быть отредактирован пользователями. Таким образом, пользователи не подвергаются деталям Spring, даже не в файлах конфигурации XML.

Как мне управлять потоком мониторинга файловой системы? Является ли хорошим дизайном ожидать, что программа создаст основной класс библиотеки и инициирует вызов или что-то в этом роде?

Я рекомендую использовать инфраструктуру Java concurrency, в частности ScheduledExecutorService, чтобы запускать задачи (задачи) мониторинга через определенные промежутки времени. Тем не менее, вы можете скрыть эту деталь реализации от пользователей вашей библиотеки, только разоблачив некоторый метод init, чтобы пройти в нужный интервал таймера.

Ответ 4

Насколько я знаю, невозможно настроить вашу библиотеку для автоматического запуска потока, вы должны определить класс как отправную точку. Используя Maven, вы можете создать исполняемую банку: http://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html В вашем основном классе простое использование:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:myspring-context.xml");      
    context.registerShutdownHook();

Для потоков вы можете попробовать либо реализовать интерфейс runnable, либо инициализировать bean, который запускает потоки с помощью spring исполнителей задач. Более элегантное решение, которое я могу предложить, создает поток в качестве pojo, а затем с помощью планировщика задач spring, как показано ниже:

<bean id="threadPojo" class="com.mydomain.ThreadPojo">
</bean>
<task:scheduled-tasks scheduler="mydomainTaskScheduler">
    <task:scheduled ref="threadPojo" method="process" fixed-delay="${delay-pool}"/>
</task:scheduled-tasks>
<task:scheduler id="mydomainTaskScheduler" pool-size="${my-pool-size}" />

Я надеюсь, что это будет полезно.