我正在将一个现有程序中的某些功能提取到一个单独的库中。
这个程序使用Spring进行依赖注入和其他任务,我希望在库中也继续使用它。
这个库需要监视文件系统中的更改,因此它会启动一些独立的线程来完成这个任务。
我不太清楚初始化这个库的选项:
如何初始化这个库的上下文?我不能假设库的用户也会使用Spring,但我可以将Spring与库一起分发。
如何管理我的文件系统监视线程?期望程序实例化库的主类并调用init或类似的方法是好的设计吗?
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默认会急切地创建它的bean。
干杯
ClassPathXmlApplicationContext
来配置Spring的例程。以下是一个示例:public class SpringContextLoader {
private static ApplicationContext ctx = null;
public static void init() {
if (ctx == null) {
ctx = ClassPathXmlApplicationContext("classpath:/applicatonContext.xml");
}
}
}
如何初始化库的上下文?我不能假设库用户也会使用Spring,但我可以将Spring与库一起分发。
您可以使用PropertyPlaceholderConfigurer
从(可能是外部的)属性文件中读取配置设置,用户可以编辑该文件。这样,用户就不会暴露给Spring的细节,甚至不需要使用XML配置文件。
如何管理我的文件系统监控线程?期望程序实例化库的主类并调用init或类似方法是好的设计吗?
我建议使用Java并发框架,特别是ScheduledExecutorService
在指定的时间间隔内运行监控任务。但是,您可能希望隐藏此实现细节,只公开某些init方法以传递所需的计时器间隔。
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:myspring-context.xml");
context.registerShutdownHook();
对于线程,您可以尝试实现可运行的接口,并初始化一个使用Spring任务执行器启动线程的bean。但是,我可以建议的更优雅的解决方案是将您的线程创建为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}" />
希望这对你有所帮助。
new Thread(new Runnable()).setDaemon(true)
,除非你想采用优美的@Scheduled
方法。 - Johan SjöbergIoC
容器,它不涉及线程模型,这些模型已经由Java语言提供。 - Johan Sjöberg