springBoot動態(tài)加載jar及如何將類注冊到IOC
具體實現(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))){ //逐個獲取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); } }
使用:
新建一模塊,寫一個簡單類:
@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; } }
建立一個公共接口,放在公共模塊,以供加載jar時候,可以獲取接口方法
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)文章
使用Mock進行業(yè)務(wù)邏輯層Service測試詳解
這篇文章主要介紹了使用Mock進行業(yè)務(wù)邏輯層Service測試詳解,mock是一種模擬對象的技術(shù),用于在測試過程中替代真實的對象,通過mock,我們可以控制被模擬對象的行為和返回值,以便進行更加精確的測試,需要的朋友可以參考下2023-08-08java實現(xiàn)一個簡單TCPSocket聊天室功能分享
這篇文章主要為大家分享了java實現(xiàn)的一個簡單TCPSocket聊天室功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-04-04Springboot詳解整合SpringSecurity實現(xiàn)全過程
Spring Security基于Spring開發(fā),項目中如果使用Springboot作為基礎(chǔ),配合Spring Security做權(quán)限更加方便,而Shiro需要和Spring進行整合開發(fā)。因此作為spring全家桶中的Spring Security在java領(lǐng)域很常用2022-07-07基于Mybatis實現(xiàn)動態(tài)數(shù)據(jù)源切換的示例代碼
在當(dāng)今的互聯(lián)網(wǎng)應(yīng)用中,微服務(wù)大行其道,隨著業(yè)務(wù)的發(fā)展和擴展,單一的數(shù)據(jù)庫無法滿足日益增長的數(shù)據(jù)需求,本文將基于 JDK17 + Spring Boot 3 和 MyBatis 框架實現(xiàn)動態(tài)切換數(shù)據(jù)源功能,需要的朋友可以參考下2024-09-09詳解SpringBoot實現(xiàn)ApplicationEvent事件的監(jiān)聽與發(fā)布
這篇文章主要為大家詳細介紹了SpringBoot如何實現(xiàn)ApplicationEvent事件的監(jiān)聽與發(fā)布,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03Jvm調(diào)優(yōu)和SpringBoot項目優(yōu)化的詳細教程
這篇文章主要介紹了Jvm調(diào)優(yōu)和SpringBoot項目優(yōu)化,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09在Windows系統(tǒng)下安裝Thrift的方法與使用講解
今天小編就為大家分享一篇關(guān)于在Windows系統(tǒng)下安裝Thrift的方法與使用講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12