spring bean 动态添加
1.场景:服务运行期间,上传jar,并根据jar中的bean-context.xml动态添加spring bean
bean-context.xml:
2.步骤:
a.自定义继承URLClassLoader的类加载jar,
HotUrlClassLoader:
public class HotUrlClassLoader extends URLClassLoader {private JarURLConnection cachedJarFile;public HotUrlClassLoader() {super(new URL[]{},findParentClassLoader());}/*** 将指定的文件url添加到类加载器的classpath中去,并缓存jar connection,方便以后卸载jar* 一个可想类加载器的classpath中添加的文件url* @return*/public void addURLFile(URL file){try { // 打开并缓存文件url连接URLConnection uc = file.openConnection();if (uc instanceof JarURLConnection){ uc.setUseCaches(true);((JarURLConnection) uc).getManifest();cachedJarFile = (JarURLConnection)uc; }} catch (Exception e){System.err.println("Failed to cache plugin JAR file: " + file.toExternalForm());}addURL(file);}public void unloadJarFile(String url){JarURLConnection jarURLConnection = cachedJarFile;if(jarURLConnection==null){return;} try {System.err.println("Unloading plugin JAR file " + jarURLConnection.getJarFile().getName());jarURLConnection.getJarFile().close();jarURLConnection=null;} catch (Exception e) {System.err.println("Failed to unload JAR file\n"+e);}}public static ClassLoader findParentClassLoader(){// ClassLoader parent=HotUrlClassLoader.class.getClassLoader();ClassLoader parent=ClassLoader.getSystemClassLoader();if(parent==null){parent=HotUrlClassLoader.class.getClassLoader();}if(parent==null){parent=ClassLoader.getSystemClassLoader();}return parent;}
}
b.使用HotLoader加载指定目录jar
public class HotLoader {
// @Resource
// private SystemConfig systemConfig;private Logger logger=LoggerFactory.getLogger(HotLoader.class);private final static String JAR_HEADER="jar:file:";private final static String JAR_END="!/";private final static ConcurrentHashMap LOADER_CACHE = new ConcurrentHashMap<>();;public HotUrlClassLoader loadJar(String jarName,ApplicationContext applicationContext){HotUrlClassLoader classLoader=LOADER_CACHE.get(jarName);if (classLoader!=null){return classLoader;}
// jarName="test.jar";classLoader=new HotUrlClassLoader();StringBuilder path =new StringBuilder();path.append(JAR_HEADER);path.append(File.separator);path.append("E:error");path.append(File.separator);path.append(jarName);path.append(JAR_END);try {URL jarURl=new URL(path.toString());classLoader.addURLFile(jarURl);LOADER_CACHE.put(jarName,classLoader);} catch (MalformedURLException e) {e.printStackTrace();}return classLoader;}public Class loadClass(String jarName,String name) throws ClassNotFoundException {ClassLoader urlClassLoader =HotUrlClassLoader.findParentClassLoader();Class c= null;try {c = urlClassLoader.loadClass(name);if(Objects.nonNull(c)){return c;}} catch (ClassNotFoundException e) {logger.info("parent classLoader not found "+name);urlClassLoader= LOADER_CACHE.get(jarName);}return urlClassLoader.loadClass(name);}public void unloadJarFile(String jarName) throws MalformedURLException {HotUrlClassLoader urlClassLoader = LOADER_CACHE.get(jarName);
// urlClassLoader.if(urlClassLoader==null){ return; } // String path = systemConfig.getExternalClassPath();String path = "E:/testspace/externalClassPath";String jarStr = "jar:file:/"+path+"/"+jarName+"!/";urlClassLoader.unloadJarFile(jarStr);urlClassLoader = null;LOADER_CACHE.remove(jarName);}
c.加载初始化jar中bean,并将bean,放到spring主上下文中
public String loadJar(String jarName) throws Exception{HotLoader classLoader = new HotLoader();try {HotUrlClassLoader jarLoader=classLoader.loadJar("creatoo-demo-1.0-SNAPSHOT.jar");ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();context.setClassLoader(jarLoader);context.setConfigLocation("/bean-context.xml");context.refresh();ConfigurableListableBeanFactory contextBeanFactory=context.getBeanFactory();DefaultListableBeanFactory capableBeanFactory=(DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();Iterator iter = contextBeanFactory.getBeanNamesIterator();while (iter.hasNext()){String beanName=iter.next().toString();if(contextBeanFactory.containsBeanDefinition(beanName)&&!capableBeanFactory.containsSingleton(beanName)){capableBeanFactory.registerSingleton(beanName,contextBeanFactory.getBean(beanName));logger.info(beanName);}}}catch (Exception e){logger.error("jar加载失败",e);throw new RuleServerException("jar加载失败");}return ResponseUtil.returnSuc("jar加载成功").toString();}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!