具有Jar文件的SpringBoot运行时动态外部配置

时间:2019-10-17 00:37:06

标签: java spring spring-boot

我正在寻找有关如何在SpringBoot中正确构建此结构的指南。

enter image description here 在我项目的核心部分,我有一个SpringBoot应用程序,该应用程序将在运行时通过属性值配置为特定的 AdapterType my.adapter.type

在此示例中,可能的值为:

Modem
Turkey
Computer
Beef

在类路径上将存在一个带有包的{strong> jar 文件:org.myapp.adapters。在该程序包中,有各种Spring @Component类,每个类都实现SystemAdapter接口,该接口指定一个type(上面列出的类型之一)和一个getType()方法。 >

应用程序将使用

@ComponentScan(basePackages = {"org.myapp.adapters"})

在启动时发现存在哪些适配器,然后将在每个适配器上调用getType()方法以发现其适用的类型。

接下来,SystemAdapterFactory会将my.adapater.type属性值与Beans的getType()方法返回的类型匹配,该方法返回给定指定类型的正确适配器。

目标是能够向其他可以编写自己的SystemAdapater库的团队提供SystemAdapter接口和枚举jar。然后在启动时,我们可以将 DefaultAdapaters.jar 换成 FoodAdapaters.jar

使用@ComponentScan注释-并假设适配器位于正确的程序包中,我认为我们可以即时交换实现-无需编译主类。

让我感到困惑的是如何实际配置Gradle和SpringBoot来完成我想要的事情。看来默认的 bootJar 任务会编译成一堆.class文件-因此,我不清楚如何实际构建此解决方案。

我想我需要3个独立的项目(或模块)

Application
Interface
AdapterImplementation

我相信如果我在Application项目中使用属性加载器配置:

bootJar {
    manifest {
        attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'
    }
}

从理论上讲,我应该能够在运行时在classPath上传递不同的Jar文件,并且它将选择它们。

这里的指导性设计原则是,如果我应该能够(在运行时)加载不同的实现jar文件并使其工作,而不必弄乱主应用程序。

所以我的问题是:

1)我是否采用正确的方法来构建结构并可能使其正常工作

2)还有一种我们错过的方法可以使事情变得更加简单吗?

谢谢

2 个答案:

答案 0 :(得分:1)

我认为SpringBatch很好地说明了您想要实现的目标。如果您对SpringBatch的默认设置感到满意,则只需使用@EnableBatchProcessing,它将使用您的环境中已指定的Bean,例如dataSourcetransactionManager

但是,如果您想更改Spring用来将批处理作业保存到另一个数据库的dataSource,则可以扩展其可用的默认配置:

package i.live.where.the.application.context.is.created;

@EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {

    @Override
    @Autowired
    public void setDataSource(@Qualifier("batchDataSource") DataSource batchDataSource) {
        super.setDataSource(batchDataSource);
    }
}

尽管对于@Autowired那些没有指定类型的依赖项,请确保使用@Qualifier可以正确实现所需的服务,或者可以将@Primary用于默认值。

我不确定我是否完全了解您的项目结构,但是我认为这种方法可能不是您想要的,因为您正在开发的模块也在初始化应用程序上下文?

如果是这种情况,则将您的域放入自己的模块中,该模块可以通过我描述的方法进行配置。然后,创建应用程序上下文的实际模块可以将您的模块包括在其类路径中,以及可以为服务实现的任何库,例如

package some.other.teams.module;

@Component("batchDataSource")
public class BatchDataSource implements your.module.DataSource {/*** ***/}

结合上面的BatchConfiguration,开发人员可以根据需要交换实现。

答案 1 :(得分:0)

我设法回答了自己的问题。我记录了我在中等情况下采取的方法: https://medium.com/@Jeef/dynamically-loading-libraries-into-a-springboot-application-at-run-time-80639ee5aab?sk=5851d25c7106307ff0f2b0a4171ab613

我还构建了一个示例项目,演示了在GitHub上的实现:https://github.com/jeeftor/SpringBoot-Dynamic-JarLoad

enter image description here