Spring Boot加载外部Jar包
项目有一个需求,需要通过spring加载配置下的Jar包,将Jar包中的类注册成Spring的一个Bean以供后续使用。
1、构建自己的ClassLoader。
关于java自己的ClassLoader的加载方式,详情可移步此篇博客。
以下是我定义的JarClassLoader,将Jar包转换为URL,通过URLClassLoader去加载。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.talend.dataprep.api.action.Action;
import org.talend.dataprep.api.action.ActionDefinition;
import java.io.*;
import java.lang.reflect.Modifier;
import java.net.*;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* @Author: chang sir
* @Date: 2021/3/11 0011上午 10:36
* @Email:
*/
public class JarUrlClassLoader extends URLClassLoader {
/** logger */
// private static final Logger LOGGER = LoggerFactory.getLogger(JarUrlClassLoader.class);
public JarUrlClassLoader(){
super(new URL[]{});
}
public JarUrlClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
@Override
protected void addURL(URL url) {
super.addURL(url);
}
}
2、构建Import通过Import注解扫描加入。
定义一个Import类,覆写ImportBeanDefinitionRegistrar接口,
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import org.talend.dataprep.JarUrlClassLoader;
import org.talend.dataprep.api.action.Action;
import org.talend.dataprep.api.action.ActionDefinition;
import org.talend.dataprep.exception.TDPException;
import org.talend.dataprep.exception.error.CommonErrorCodes;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author: chang sir
* @Date: 2021/3/11 0011下午 19:24
* @Email:
*/
public class PlugActionImport implements ImportBeanDefinitionRegistrar {
/** logger */
private static final Logger LOGGER = LoggerFactory.getLogger(PlugActionImport.class);
public static final String PREFIX = "action#";
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
GenericApplicationContext context = new GenericApplicationContext();
String jarPath = jarPath();
JarUrlClassLoader loader = getLoader();
if(StringUtils.isEmpty(jarPath)){
LOGGER.info("please config a absolute path for action plug jar. ex: /data/java/***.jar,");
}