java - SpringBoot运行时动态外部配置Jar文件

标签 java spring spring-boot

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

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

对于此示例,可能的值为:

Modem
Turkey
Computer
Beef

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

应用程序将使用

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

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

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

目标是能够向其他可以编写自己的 SystemAdapter 库的团队提供 SystemAdapter 接口(interface)和 Enum 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)是否有另一种我们错过的方法可以让事情变得更简单?

谢谢

最佳答案

我认为 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 结合使用,开发人员能够根据需要交换实现。

关于java - SpringBoot运行时动态外部配置Jar文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58423349/

相关文章:

java - java中的类定义

java - spring boot无法解析html View

docker - 在 vagrant 和 docker 中调试 spring boot

java - 无法解析 org.springframework.cloud :spring-cloud-starter-netflix-eureka-client:unknown

java - 自定义 checkstyle 配置忽略标准规则?

java - 在java中的方法调用中使用变量

java - 缓存声音并创建它的实例

java - 可选的 Spring bean 引用

spring - 从 Spring Boot 配置中排除 Java 系统属性和环境变量

java - 使用 Gradle 和 Docker 部署 Spring Boot/PostgreSQL 项目