springBoot动态加载jar,将类注册到IOC
具体实现
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}/{b}")
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);
}
原文地址:https://blog.csdn.net/m0_73363097/article/details/143467506
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!