springBoot動態(tài)加載jar及如何將類注冊到IOC
具體實(shí)現(xiàn)
Service
public interface JarService {
Boolean loadJarByName(LoadJarDTO dto);
}impl:
@Service
@RequiredArgsConstructor
@Slf4j
public class JarServiceImpl implements JarService {
private final SpringContextUtil springContextUtil;
@Override
public Boolean loadJarByName(LoadJarDTO dto) {
//初始化File-加載jar所在目錄
File jarFile = new File(dto.getJarPath());
if (!jarFile.exists()){
return false;
}
List<String> loadClassList = this.getLoadClass(jarFile.getAbsolutePath());
if (CollectionUtils.isEmpty(loadClassList)){
return false;
}
//加載jar
ClassLoader classLoader = ClassLoaderUtil.getJarClassLoader(jarFile);
for (String loadClassPath : loadClassList) {
Class<?> clazz = null;
try {
clazz = classLoader.loadClass(loadClassPath);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
if(!this.isLoadClass(clazz)){
continue;
}
//生成需要注冊到ioc的bean名稱
// clazz.getSimpleName()用于獲取表示該類的簡單名稱(不包括包名)。簡單名稱就是類名本身,而不帶任何修飾或包的前綴。
String beanName = getBeanName(dto.getPreBeanName(),clazz.getSimpleName()) ;
//加載需要加載的
if (!dto.getIsOverLoad() && springContextUtil.containsBeanDefinition(beanName)){
continue;
}
if (dto.getIsOverLoad() && springContextUtil.containsBeanDefinition(beanName)){
springContextUtil.unregisterBean(beanName);
}
springContextUtil.registerBean(beanName,clazz);
}
return true;
}
private static String getBeanName(String name, String className) {
return StringUtils.uncapitalize(name) + StringUtils.capitalize(className);
}
private boolean isLoadClass(Class<?> clazz) {
if (clazz == null){
return false;
}
//是否是接口
if (clazz.isInterface()){
return false;
}
//是否是抽象類
if (Modifier.isAbstract(clazz.getModifiers())){
return false;
}
if (clazz.getAnnotation(Service.class) != null){
return true;
}
if (clazz.getAnnotation(Component.class) != null){
return true;
}
if (clazz.getAnnotation(Repository.class) != null){
return true;
}
if (clazz.getAnnotation(Configuration.class) != null){
return true;
}
return false;
}
private List<String> getLoadClass(String jarPath) {
Set<String> classPathList = new HashSet<>();
File file = new File(jarPath);
//獲取jar的流,打開jar文件
try ( JarInputStream jarInputStream = new JarInputStream(FileUtil.getInputStream(file))){
//逐個(gè)獲取jar種文件
JarEntry jarEntry = jarInputStream.getNextJarEntry();
//遍歷
while (jarEntry != null){
//獲取文件路徑
String name = jarEntry.getName();
if (name.endsWith(".class")){
String classNamePath = name.replace(".class", "").replace("/",".");
classPathList.add(classNamePath);
}
jarEntry = jarInputStream.getNextJarEntry();
}
} catch (IOException e) {
log.error(e.getMessage());
throw new RuntimeException("獲取加載類路徑失敗");
}
return new ArrayList<>(classPathList);
}
}使用:
新建一模塊,寫一個(gè)簡單類:
@Service
public class CalculateServiceImpl implements CalculateService {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int minus(int a, int b) {
return a - b;
}
}建立一個(gè)公共接口,放在公共模塊,以供加載jar時(shí)候,可以獲取接口方法
public interface CalculateService {
int add(int a,int b);
int minus(int a ,int b);
}然后 cleam-install打成jar
建立一加載使用:
@GetMapping("/calculate/{beanName}/{a}/")
private Integer calculate( @PathVariable(value = "beanName") String beanName,
@PathVariable(value = "a") Integer a, @PathVariable("b") Integer b){
return jarService.calculate(beanName,a,b);
}
@Override
public Integer calculate(String beanName, Integer a, Integer b) {
CalculateService calculateService = SpringContextUtil.getBean(getBeanName(beanName,beanName+"Impl"), CalculateService.class);
int add = calculateService.add(a, b);
return add;
}
private static String getBeanName(String name, String className) {
return StringUtils.uncapitalize(name) + StringUtils.capitalize(className);
}到此這篇關(guān)于springBoot動態(tài)加載jar,將類注冊到IOC的文章就介紹到這了,更多相關(guān)springBoot動態(tài)加載jar內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot 整合 langchain4j 實(shí)現(xiàn)簡單的問答功能
最近在學(xué)習(xí)langchain4j,本文將介紹如何使用langchain4j快速實(shí)現(xiàn)一個(gè)簡單的問答功能,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2025-04-04
解讀Java和JavaScript區(qū)別與聯(lián)系
這篇文章主要介紹了解讀Java和JavaScript區(qū)別與聯(lián)系,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(49)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-08-08
java設(shè)計(jì)模式之單例模式學(xué)習(xí)
單例對象(Singleton)是一種常用的設(shè)計(jì)模式。在Java應(yīng)用中,單例對象能保證在一個(gè)JVM中,該對象只有一個(gè)實(shí)例存在2014-01-01
Mybatis plus 配置多數(shù)據(jù)源的實(shí)現(xiàn)示例
這篇文章主要介紹了Mybatis plus 配置多數(shù)據(jù)源的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
Java中的UrlDecoder 和 UrlEncoder_動力節(jié)點(diǎn)Java學(xué)院整理
HTML 格式編碼的實(shí)用工具類。該類包含了將 String 轉(zhuǎn)換為 application/x-www-form-urlencoded MIME 格式的靜態(tài)方法。下文通過實(shí)例代碼給大家介紹Java中的UrlDecoder 和 UrlEncoder知識,感興趣的的朋友一起看看吧2017-07-07
Java命令行參數(shù)解析工具jcommander詳解
這篇文章主要為大家介紹了Java命令行參數(shù)解析工具jcommander命令詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Java使用CompletableFuture實(shí)現(xiàn)異步編程
在現(xiàn)代 Java 開發(fā)中,異步編程是一項(xiàng)重要技能,而 CompletableFuture 是從 Java 8 開始提供的一個(gè)功能強(qiáng)大的工具,用于簡化異步任務(wù)的編寫和組合,本文將詳細(xì)介紹 CompletableFuture 的基本使用和一些常見的應(yīng)用場景,需要的朋友可以參考下2025-01-01

