我正在寻找有关如何在SpringBoot中正确构建此结构的指南。
在我项目的核心部分,我有一个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)还有一种我们错过的方法可以使事情变得更加简单吗?
谢谢
答案 0 :(得分:1)
我认为SpringBatch
很好地说明了您想要实现的目标。如果您对SpringBatch
的默认设置感到满意,则只需使用@EnableBatchProcessing
,它将使用您的环境中已指定的Bean,例如dataSource
,transactionManager
等
但是,如果您想更改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