java 动态加载可插拔引入 jar包的plugin方法

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();
			}
		}
	}
	
	
	
}

大同小异 自己去理解。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值