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進(jìn)行業(yè)務(wù)邏輯層Service測試詳解
這篇文章主要介紹了使用Mock進(jìn)行業(yè)務(wù)邏輯層Service測試詳解,mock是一種模擬對象的技術(shù),用于在測試過程中替代真實的對象,通過mock,我們可以控制被模擬對象的行為和返回值,以便進(jìn)行更加精確的測試,需要的朋友可以參考下2023-08-08
java實現(xiàn)一個簡單TCPSocket聊天室功能分享
這篇文章主要為大家分享了java實現(xiàn)的一個簡單TCPSocket聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-04-04
Springboot詳解整合SpringSecurity實現(xiàn)全過程
Spring Security基于Spring開發(fā),項目中如果使用Springboot作為基礎(chǔ),配合Spring Security做權(quán)限更加方便,而Shiro需要和Spring進(jìn)行整合開發(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ā)展和擴(kuò)展,單一的數(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ā)布
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實現(xiàn)ApplicationEvent事件的監(jiān)聽與發(fā)布,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03
Jvm調(diào)優(yōu)和SpringBoot項目優(yōu)化的詳細(xì)教程
這篇文章主要介紹了Jvm調(diào)優(yōu)和SpringBoot項目優(yōu)化,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
在Windows系統(tǒng)下安裝Thrift的方法與使用講解
今天小編就為大家分享一篇關(guān)于在Windows系統(tǒng)下安裝Thrift的方法與使用講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12

