package com.hulu.spi.plugin;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.UUID;
import java.util.stream.Stream;
public class PluginClassLoader extends URLClassLoader {
private List<JarURLConnection> cacheJarFiles=new ArrayList<JarURLConnection>();
private String name;
public PluginClassLoader() {
super(new URL[] {},findParentClassLoader());
this.name=UUID.randomUUID().toString();
}
public PluginClassLoader(String name) {
super(new URL[] {},findParentClassLoader());
this.name = name;
}
public void addUrlFile(String ... paths) {
URL[] urls= Stream.of(paths).map(path->new File(path)).flatMap(file->{
if(file.isDirectory()) {
try {
return Files.walk(Path.of(file.getPath())).map(path->path.toFile());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}else {
return Stream.of(file);
}
}).filter(file->file.getName().endsWith(".jar")).map(file-> {
try {
return new URL("jar:file:/"+file.getAbsolutePath()+"!/");
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}).toArray(URL[]::new);
addUrlFile(urls);
}
//
public void addUrlFile(URL ... urls) {
for(URL url:urls) {
try {
URLConnection uc=url.openConnection();
if(uc instanceof JarURLConnection) {
uc.setUseCaches(true);
JarURLConnection juc=(JarURLConnection) uc;
juc.getManifest();
cacheJarFiles.add(juc);
addURL(url);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void unloadJarFile() {
for(JarURLConnection juc: cacheJarFiles) {
try {
juc.getJarFile().close();
} catch (IOException e) {
e.printStackTrace();
}
}
cacheJarFiles.clear();
}
private static ClassLoader findParentClassLoader() {
ClassLoader parent=PluginClassLoader.class.getClassLoader();
if(parent==null) {
parent=ClassLoader.getSystemClassLoader();
}
return parent;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PluginClassLoader other = (PluginClassLoader) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public List<JarURLConnection> getCacheJarFiles() {
return cacheJarFiles;
}
public void setCacheJarFiles(List<JarURLConnection> cacheJarFiles) {
this.cacheJarFiles = cacheJarFiles;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* SPI need add resource dir path 'META-INF/services/'
* @param <S>
* @param service
* @return
*/
public <S> ServiceLoader<S> get(Class<S> service){
return ServiceLoader.load(service, this);
}
}
package com.hulu.spi.plugin;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
public class PluginManager {
private HashMap<String, PluginClassLoader> pluginMap=new HashMap<String, PluginClassLoader>();
public void addPluginClassLoader(String loadName,String ... paths) {
removePluginClassLoader(loadName);
PluginClassLoader pcl=new PluginClassLoader(loadName);
pcl.addUrlFile(paths);
pluginMap.put(loadName, pcl);
}
public Class getClass(String loadName,String className) {
PluginClassLoader pcl=pluginMap.get(loadName);
Class clazz=null;
if(pcl!=null) {
try {
clazz = pcl.loadClass(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return clazz;
}
public <S> S getNewObject(String loadName,String className,Class<S> clazzPresen) {
Class clazz= getClass(loadName, className);
if(clazzPresen.isAnnotationPresent(clazz)) {
try {
return (S) clazz.getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
return null;
}
public void removePluginClassLoader(String loadName) {
PluginClassLoader pcl=pluginMap.remove(loadName);
if(pcl!=null) {
pcl.unloadJarFile();
try {
pcl.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
大同小异 自己去理解。