springBoot動(dòng)態(tài)加載jar及如何將類(lèi)注冊(cè)到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; } //生成需要注冊(cè)到ioc的bean名稱(chēng) // clazz.getSimpleName()用于獲取表示該類(lèi)的簡(jiǎn)單名稱(chēng)(不包括包名)。簡(jiǎn)單名稱(chēng)就是類(lèi)名本身,而不帶任何修飾或包的前綴。 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; } //是否是抽象類(lèi) 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的流,打開(kāi)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("獲取加載類(lèi)路徑失敗"); } return new ArrayList<>(classPathList); } }
使用:
新建一模塊,寫(xiě)一個(gè)簡(jiǎn)單類(lèi):
@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動(dòng)態(tài)加載jar,將類(lèi)注冊(cè)到IOC的文章就介紹到這了,更多相關(guān)springBoot動(dòng)態(tài)加載jar內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot 啟動(dòng)如何排除某些bean的注入
這篇文章主要介紹了springboot 啟動(dòng)如何排除某些bean的注入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08使用Mock進(jìn)行業(yè)務(wù)邏輯層Service測(cè)試詳解
這篇文章主要介紹了使用Mock進(jìn)行業(yè)務(wù)邏輯層Service測(cè)試詳解,mock是一種模擬對(duì)象的技術(shù),用于在測(cè)試過(guò)程中替代真實(shí)的對(duì)象,通過(guò)mock,我們可以控制被模擬對(duì)象的行為和返回值,以便進(jìn)行更加精確的測(cè)試,需要的朋友可以參考下2023-08-08java實(shí)現(xiàn)一個(gè)簡(jiǎn)單TCPSocket聊天室功能分享
這篇文章主要為大家分享了java實(shí)現(xiàn)的一個(gè)簡(jiǎn)單TCPSocket聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04Springboot詳解整合SpringSecurity實(shí)現(xiàn)全過(guò)程
Spring Security基于Spring開(kāi)發(fā),項(xiàng)目中如果使用Springboot作為基礎(chǔ),配合Spring Security做權(quán)限更加方便,而Shiro需要和Spring進(jìn)行整合開(kāi)發(fā)。因此作為spring全家桶中的Spring Security在java領(lǐng)域很常用2022-07-07基于Mybatis實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的示例代碼
在當(dāng)今的互聯(lián)網(wǎng)應(yīng)用中,微服務(wù)大行其道,隨著業(yè)務(wù)的發(fā)展和擴(kuò)展,單一的數(shù)據(jù)庫(kù)無(wú)法滿(mǎn)足日益增長(zhǎng)的數(shù)據(jù)需求,本文將基于 JDK17 + Spring Boot 3 和 MyBatis 框架實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源功能,需要的朋友可以參考下2024-09-09詳解SpringBoot實(shí)現(xiàn)ApplicationEvent事件的監(jiān)聽(tīng)與發(fā)布
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實(shí)現(xiàn)ApplicationEvent事件的監(jiān)聽(tīng)與發(fā)布,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03Jvm調(diào)優(yōu)和SpringBoot項(xiàng)目?jī)?yōu)化的詳細(xì)教程
這篇文章主要介紹了Jvm調(diào)優(yōu)和SpringBoot項(xiàng)目?jī)?yōu)化,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09在Windows系統(tǒng)下安裝Thrift的方法與使用講解
今天小編就為大家分享一篇關(guān)于在Windows系統(tǒng)下安裝Thrift的方法與使用講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12