wordpress建视频网站,市北网站建设,建网站系统,移动网站开发与维护Jdk8 动态编译 Java 源码为 Class 文件 一.JDK版本二.工程介绍1.依赖2.启动类3.配置类#xff08;用于测试依赖注入#xff09;4.工具类1.Java 源码文件读取类2.SpringBoot 容器实例管理类 5.测试类1.抽象类2.接口类3.默认抽象实现4.默认接口实现 6.接口类1.测试接口2.类重载… Jdk8 动态编译 Java 源码为 Class 文件 一.JDK版本二.工程介绍1.依赖2.启动类3.配置类用于测试依赖注入4.工具类1.Java 源码文件读取类2.SpringBoot 容器实例管理类 5.测试类1.抽象类2.接口类3.默认抽象实现4.默认接口实现 6.接口类1.测试接口2.类重载控制接口 7.动态编译类1.类加载器2.类管理器3.类对象4.Java 文件类 8.配置文件 三.测试1.测试用类1.测试类原类修改 2.测试1.原类直接打印2.原类修改 四.Jar 反编译记录 一.JDK版本 二.工程介绍
动态源码编译需要自定义类加载器JVM会根据所属类加载器和全类名判断是否为同一个类所以动态编译和加载时同一个类无法用同一个类加载器加载两次除非从 JVM 层面移除旧的类。 同一个类由不同类加载器加载时JVM 会判断为非同类所以无法直接实例化后强转为同一类型的实例需要基于接口、抽象类来实现动态替换 1.依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdorg.example/groupIdartifactIdspring-dynamic/artifactIdversion1.0-SNAPSHOT/versionpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncodingspring.version2.7.4/spring.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactIdversion${spring.version}/versionexclusionsexclusiongroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-logging/artifactId/exclusion/exclusions/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-log4j2/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.26/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-loader/artifactIdversion${spring.version}/version/dependencydependencygroupIdcom.sun/groupIdartifactIdtools/artifactIdversion1.8.0_341/versionscopesystem/scopesystemPath${JAVA_HOME}\lib\tools.jar/systemPath/dependency/dependenciesbuildfinalNamedynamic-demo/finalNamepluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdversion2.7.4/versionexecutionsexecutiongoalsgoalrepackage/goal/goals/execution/executions!-- for tools.jar --
!-- configuration--
!-- includeSystemScopetrue/includeSystemScope--
!-- /configuration--/plugin/plugins/build
/project2.启动类
package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** author* date 2023-08-10 9:51* since 1.8*/
SpringBootApplication
public class DynamicApp {public static void main(String[] args) {SpringApplication.run(DynamicApp.class,args);}
}
3.配置类用于测试依赖注入
package com.example.config;import org.springframework.stereotype.Component;/*** author moon* date 2023-08-30 14:58* since 1.8*/
Component
public class KafkaConfig {public void getConfig(){System.out.println(kafka config);}
}
4.工具类
1.Java 源码文件读取类
package com.example.util;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;/*** author moon* date 2023-08-31 9:25* since 1.8*/
public class FileUtil {public static String readJson(String filePath){if (org.springframework.util.StringUtils.hasLength(filePath)){InputStream inputStream null;StringBuilder builder new StringBuilder();try {int batchSize 2048;inputStream new FileInputStream(filePath);byte[] temp new byte[batchSize];int read;while ((read inputStream.read(temp)) ! -1){if (read batchSize){byte[] tail Arrays.copyOf(temp,read);builder.append(new String(tail));} else {builder.append(new String(temp));}}return builder.toString();} catch (IOException e) {return ;} finally {if (null ! inputStream){try {inputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}}}return ;}}
2.SpringBoot 容器实例管理类
package com.example.util;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** author moon* date 2023-08-31 11:18* since 1.8*/
Component
public class SpringBeanUtil implements ApplicationContextAware {private static ApplicationContext applicationContext;private static ConfigurableApplicationContext context ;/*** 获取 Bean 工厂*/private static DefaultListableBeanFactory beanFactory ;Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringBeanUtil.applicationContext applicationContext;SpringBeanUtil.context (ConfigurableApplicationContext) applicationContext;SpringBeanUtil.beanFactory (DefaultListableBeanFactory) context.getBeanFactory();}/*** 替换 bean 并获取新的* param beanName* param clazz* return*/public static Object replace(String beanName,Class clazz){//卸载unregister(beanName);//注册register(beanName,clazz);//获取return getBean(beanName);}/*** 注册 Bean* param clazz*/public static void register(String beanName,Class clazz){BeanDefinitionBuilder builder BeanDefinitionBuilder.genericBeanDefinition(clazz);BeanDefinition definition builder.getBeanDefinition();//为 definition 设置额外属性definition.setScope(singleton);//注册beanFactory.registerBeanDefinition(beanName,definition);}/*** 卸载 Bean* param beanName*/public static void unregister(String beanName){if (beanFactory.containsBean(beanName)){beanFactory.removeBeanDefinition(beanName);}}/*** 获取所有 Bean* return*/public static ListString getBeans(){String[] names applicationContext.getBeanDefinitionNames();ListString beans new ArrayList(names.length);for (String name:names){beans.add(applicationContext.getBean(name).getClass().getName());}return beans;}/*** bean 是否存在* param name* return*/public static boolean isBeanExist(String name){return applicationContext.containsBean(name);}/*** 通过名称获取 Bean* param name* return* param T* throws BeansException*/public static T T getBean(String name) throws BeansException{return (T) applicationContext.getBean(name);}/*** 通过类型获取 Bean* param clazz* return* param T* throws BeansException*/public static T T getBean(Class? clazz) throws BeansException{return (T) applicationContext.getBean(clazz);}/*** 获取指定类型的 Bean 的名称* param className* return* throws BeansException*/public static ListString getBeanName(String className) throws BeansException, ClassNotFoundException {Class? clazz Class.forName(className);return Arrays.asList(applicationContext.getBeanNamesForType(clazz));}
}
5.测试类
1.抽象类
package com.example.service;/*** author moon* date 2023-08-30 14:15* since 1.8*/
public abstract class TestAbstract {/*** 抽象方法* param str*/public abstract void hand(String str);
}
2.接口类
package com.example.service;/*** author moon* date 2023-08-31 10:58* since 1.8*/
public interface TestService {/*** 处理* param str*/void hand(String str);}
3.默认抽象实现
package com.example.service.impl;import com.example.config.KafkaConfig;
import com.example.service.TestAbstract;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** author moon* date 2023-08-31 11:01* since 1.8*/
Component
public class TestAbstractImpl extends TestAbstract {AutowiredKafkaConfig config;Value(${my.ip})String ip;Overridepublic void hand(String str) {config.getConfig();System.out.println(str);System.out.println(ip);}
}
4.默认接口实现
package com.example.service.impl;import com.example.config.KafkaConfig;
import com.example.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** author moon* date 2023-08-31 10:59* since 1.8*/
Service
public class TestServiceImpl implements TestService {AutowiredKafkaConfig config;Overridepublic void hand(String str) {config.getConfig();System.out.println(hand: this);}
}
6.接口类
1.测试接口
package com.example.controller;import com.example.service.TestAbstract;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** author moon* date 2023-08-30 17:27* since 1.8*/
RestController
RequestMapping(/test)
public class TestController {/*** 引入抽象类依赖*/Resource(name testAbstractImpl)TestAbstract testAbstract;GetMapping(/print)public void print(String content){testAbstract.hand(Hello : content);}
}
2.类重载控制接口
package com.example.controller;import com.example.dynamic.MemoryClassLoader;
import com.example.service.TestAbstract;
import com.example.util.FileUtil;
import com.example.util.SpringBeanUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;/*** author moon* date 2023-08-30 14:10* since 1.8*/
RestController
RequestMapping(/reload)
public class Reload extends ClassLoader{GetMapping(/re)public void re(String name,String beanName) throws InstantiationException, IllegalAccessException, InvocationTargetException, MalformedURLException, NoSuchMethodException, ClassNotFoundException {String className com.example.service.impl. name;String classPath C:\\Users\\administrator\\Desktop\\jar\\name.java;String javaStr FileUtil.readJson(classPath);/*** 定义新的 MemoryClassLoader 同一个 MemoryClassLoader 不能两次加载同一个类*/MemoryClassLoader loader new MemoryClassLoader();loader.registerJava(className,javaStr);Class clazz loader.findClass(className);TestAbstract handler (TestAbstract) clazz.getDeclaredConstructor().newInstance();// 将外部Jar包中的Bean注入到Spring容器中Object obj SpringBeanUtil.replace(beanName,clazz);TestAbstract test (TestAbstract) obj;test.hand(sss);System.out.println();}}
7.动态编译类
1.类加载器
package com.example.dynamic;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** author moon*/
Slf4j
Component
public class MemoryClassLoader extends URLClassLoader {/*** 缓存字节码*/private MapString, byte[] classBytesMap new ConcurrentHashMap();/*** 构造*/public MemoryClassLoader() {super(new URL[0], MemoryClassLoader.class.getClassLoader());}/*** 注册 Java 字符串到内存类加载器中** param className 类名字* param javaStr Java字符串*/public void registerJava(String className, String javaStr) {try {this.classBytesMap.putAll(compile(className, javaStr));} catch (Exception e) {log.error(register java class exception:);}}/*** 编译 Java 源码** param className 类名字* param javaStr Java代码* return class 二进制*/private MapString, byte[] compile(String className, String javaStr) {//初始化编译器JavaCompiler compiler ToolProvider.getSystemJavaCompiler();//获取Java文件管理器try (MemoryJavaFileManager manager new MemoryJavaFileManager()) {JavaFileObject javaFileObject manager.makeStringSource(className, javaStr);JavaCompiler.CompilationTask task compiler.getTask(null, manager, null, null, null, Arrays.asList(javaFileObject));if (task.call()) {return manager.getClassBytes();}} catch (Exception e) {log.error(compile java str exception:,e);}return null;}/*** 获取 Class* param name the name of the class* return* throws ClassNotFoundException*/Overridepublic Class? findClass(String name) throws ClassNotFoundException {byte[] buf classBytesMap.get(name);if (buf null) {return super.findClass(name);}classBytesMap.remove(name);return defineClass(name, buf, 0, buf.length);}/*** 获取jar包所在路径** return jar包所在路径*/public static String getPath() {ApplicationHome home new ApplicationHome(MemoryJavaFileManager.class);String path home.getSource().getPath();return path;}/*** 判断是否jar模式运行** return*/public static boolean isJar() {return getPath().endsWith(.jar);}}2.类管理器
package com.example.dynamic;import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import org.springframework.boot.loader.jar.JarFile;
import javax.tools.*;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.stream.Collectors;/*** Java 文件管理器* 用于加载 SpringBoot 下面的依赖资源** author moon* date 2023-08-10 9:58* since 1.8*/
public class MemoryJavaFileManager extends ForwardingJavaFileManagerJavaFileManager {/*** 缓存字节码*/final MapString, byte[] classBytesMap new ConcurrentHashMap();/*** 缓存文件对象*/final MapString, ListJavaFileObject classObjectPackageMap new ConcurrentHashMap();/*** 文件管理器*/private JavacFileManager javaFileManager;/*** 包名 / JavaFile(.java)*/public final static MapString, ListJavaFileObject CLASS_OBJECT_PACKAGE_MAP new ConcurrentHashMap();/*** 锁对象*/private static final Object lock new Object();/*** 初始化标识*/private static boolean isInit false;/*** 初始化*/public void init() {try {JarFile tempJarFile;ListJavaFileObject javaFiles;String packageName,className;//获取当前 Jar 包String jarBaseFile MemoryClassLoader.getPath();//加载 Jar 包JarFile jarFile new JarFile(new File(jarBaseFile));//取包自身文件for (JarEntry entry:jarFile){//SpringBoot repackage 打包 class 文件带一个 BOOT-INF/classes/ 之后才是包名String name entry.getName().replace(BOOT-INF/classes/,);String classPath name.replace(/, .);//如果不是 class 文件跳过if (name.endsWith(.class)){//取出包名packageName classPath.substring(0, name.lastIndexOf(/));//取类名className classPath.replace(.class, );//创建集合javaFiles Optional.ofNullable(CLASS_OBJECT_PACKAGE_MAP.get(packageName)).orElse(new ArrayList()) ;//取 JavaFilefilterClass(packageName,className,jarFile.getUrl(),entry.getName(),javaFiles);}}//遍历取内部 Jar 包ListJarEntry entries jarFile.stream().filter(jarEntry - {return jarEntry.getName().endsWith(.jar);}).collect(Collectors.toList());// Jar Filefor (JarEntry entry : entries) {//取内部文件tempJarFile jarFile.getNestedJarFile(jarFile.getEntry(entry.getName()));//跳过工具包 Jarif (tempJarFile.getName().contains(tools.jar)) {continue;}//遍历 Jar 文件EnumerationJarEntry tempEntriesEnum tempJarFile.entries();while (tempEntriesEnum.hasMoreElements()) {JarEntry jarEntry tempEntriesEnum.nextElement();String classPath jarEntry.getName().replace(/, .);//如果不是 class 文件跳过if (!classPath.endsWith(.class) || jarEntry.getName().lastIndexOf(/) -1) {continue;} else {//取出包名packageName classPath.substring(0, jarEntry.getName().lastIndexOf(/));//取类名className jarEntry.getName().replace(/, .).replace(.class, );//创建集合javaFiles Optional.ofNullable(CLASS_OBJECT_PACKAGE_MAP.get(packageName)).orElse(new ArrayList()) ;//取 JavaFilefilterClass(packageName,className,tempJarFile.getUrl(),jarEntry.getName(),javaFiles);}}}} catch (Exception e) {e.printStackTrace();}isInit true;}/*** 取 class* param packageName* param className* param url* param entryName* param javaFiles*/private void filterClass(String packageName,String className,URL url,String entryName,ListJavaFileObject javaFiles) throws MalformedURLException {//取 JavaFilejavaFiles.add(new MemorySpringBootInfoJavaClassObject(className, new URL(url, entryName), javaFileManager));//缓存 Package / JavaFileCLASS_OBJECT_PACKAGE_MAP.put(packageName, javaFiles);}/*** 构造*/MemoryJavaFileManager() {super(getStandardFileManager(null, null, null));this.javaFileManager (JavacFileManager) fileManager;}/*** 获取文件对象集合* param packageName* return*/public ListJavaFileObject getLibJarsOptions(String packageName) {synchronized (lock) {if (!isInit) {init();}}return CLASS_OBJECT_PACKAGE_MAP.get(packageName);}Overridepublic IterableJavaFileObject list(Location location,String packageName,SetJavaFileObject.Kind kinds,boolean recurse)throws IOException {if (CLASS_PATH.equals(location.getName()) MemoryClassLoader.isJar()) {ListJavaFileObject result getLibJarsOptions(packageName);if (result ! null) {return result;}}IterableJavaFileObject it super.list(location, packageName, kinds, recurse);if (kinds.contains(JavaFileObject.Kind.CLASS)) {final ListJavaFileObject javaFileObjectList classObjectPackageMap.get(packageName);if (javaFileObjectList ! null) {if (it ! null) {for (JavaFileObject javaFileObject : it) {javaFileObjectList.add(javaFileObject);}}return javaFileObjectList;} else {return it;}} else {return it;}}Overridepublic String inferBinaryName(Location location, JavaFileObject file) {if (file instanceof MemoryInputJavaClassObject) {return ((MemoryInputJavaClassObject) file).inferBinaryName();}return super.inferBinaryName(location, file);}Overridepublic JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind,FileObject sibling) throws IOException {if (kind JavaFileObject.Kind.CLASS) {return new MemoryOutputJavaClassObject(className);} else {return super.getJavaFileForOutput(location, className, kind, sibling);}}/*** 设置源码* param className* param code* return*/JavaFileObject makeStringSource(String className, final String code) {String classPath className.replace(., /) JavaFileObject.Kind.SOURCE.extension;return new SimpleJavaFileObject(URI.create(string:/// classPath), JavaFileObject.Kind.SOURCE) {Overridepublic CharBuffer getCharContent(boolean ignoreEncodingErrors) {return CharBuffer.wrap(code);}};}/*** 设置字节码* param className* param bs*/void makeBinaryClass(String className, final byte[] bs) {JavaFileObject javaFileObject new MemoryInputJavaClassObject(className, bs);String packageName ;int pos className.lastIndexOf(.);if (pos 0) {packageName className.substring(0, pos);}ListJavaFileObject javaFileObjectList classObjectPackageMap.get(packageName);if (javaFileObjectList null) {javaFileObjectList new LinkedList();javaFileObjectList.add(javaFileObject);classObjectPackageMap.put(packageName, javaFileObjectList);} else {javaFileObjectList.add(javaFileObject);}}/*** 内部输入类*/class MemoryInputJavaClassObject extends SimpleJavaFileObject {final String className;final byte[] bs;MemoryInputJavaClassObject(String className, byte[] bs) {super(URI.create(string:/// className.replace(., /) Kind.CLASS.extension), Kind.CLASS);this.className className;this.bs bs;}Overridepublic InputStream openInputStream() {return new ByteArrayInputStream(bs);}public String inferBinaryName() {return className;}}/*** 内部输出类*/class MemoryOutputJavaClassObject extends SimpleJavaFileObject {final String className;MemoryOutputJavaClassObject(String className) {super(URI.create(string:/// className.replace(., /) Kind.CLASS.extension), Kind.CLASS);this.className className;}Overridepublic OutputStream openOutputStream() {return new FilterOutputStream(new ByteArrayOutputStream()) {Overridepublic void close() throws IOException {out.close();ByteArrayOutputStream bos (ByteArrayOutputStream) out;byte[] bs bos.toByteArray();classBytesMap.put(className, bs);makeBinaryClass(className, bs);}};}}/*** 获取编译结果* return*/public MapString, byte[] getClassBytes() {return new HashMap(this.classBytesMap);}/*** 刷新* throws IOException*/Overridepublic void flush() throws IOException {}/*** 关闭* throws IOException*/Overridepublic void close() throws IOException {classBytesMap.clear();}/*** 自定义 Java 文件管理器** param var1* param var2* param var3* return*/public static SpringJavaFileManager getStandardFileManager(DiagnosticListener? super JavaFileObject var1, Locale var2, Charset var3) {Context var4 new Context();var4.put(Locale.class, var2);if (var1 ! null) {var4.put(DiagnosticListener.class, var1);}PrintWriter var5 var3 null ? new PrintWriter(System.err, true) : new PrintWriter(new OutputStreamWriter(System.err, var3), true);var4.put(Log.outKey, var5);return new SpringJavaFileManager(var4, true, var3);}
}
3.类对象
package com.example.dynamic;import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.file.JavacFileManager;import javax.tools.JavaFileObject;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;/*** 用来读取 spring boot 的 class** author moon* date 2023-08-10 9:57* since 1.8*/
public class MemorySpringBootInfoJavaClassObject extends BaseFileObject {private final String className;private URL url;public MemorySpringBootInfoJavaClassObject(String className, URL url, JavacFileManager javacFileManager) {super(javacFileManager);this.className className;this.url url;}Overridepublic JavaFileObject.Kind getKind() {return JavaFileObject.Kind.valueOf(CLASS);}Overridepublic URI toUri() {try {return url.toURI();} catch (URISyntaxException e) {e.printStackTrace();}return null;}Overridepublic String getName() {return className;}Overridepublic InputStream openInputStream() {try {return url.openStream();} catch (IOException e) {e.printStackTrace();}return null;}Overridepublic OutputStream openOutputStream() throws IOException {return null;}Overridepublic CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {return null;}Overridepublic Writer openWriter() throws IOException {return null;}Overridepublic long getLastModified() {return 0;}Overridepublic boolean delete() {return false;}public String inferBinaryName() {return className;}Overridepublic String getShortName() {return className.substring(className.lastIndexOf(.));}Overrideprotected String inferBinaryName(Iterable? extends File iterable) {return className;}Overridepublic boolean equals(Object o) {return false;}Overridepublic int hashCode() {return 0;}Overridepublic boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {return false;}
}4.Java 文件类
package com.example.dynamic;import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.ListBuffer;
import java.io.File;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.util.Iterator;/*** Java 文件管理器** author moon* date 2023-08-10 9:53* since 1.8*/
public class SpringJavaFileManager extends JavacFileManager {/**** param context* param b* param charset*/public SpringJavaFileManager(Context context, boolean b, Charset charset) {super(context, b, charset);}/*** 重写类加载器* param location a location* return*/Overridepublic ClassLoader getClassLoader(Location location) {nullCheck(location);Iterable var2 this.getLocation(location);if (var2 null) {return null;} else {ListBuffer var3 new ListBuffer();Iterator var4 var2.iterator();while (var4.hasNext()) {File var5 (File) var4.next();try {var3.append(var5.toURI().toURL());} catch (MalformedURLException var7) {throw new AssertionError(var7);}}return this.getClassLoader((URL[]) var3.toArray(new URL[var3.size()]));}}/*** 获取 LaunchedURLClassLoader 加载器** param var1* return*/Overrideprotected ClassLoader getClassLoader(URL[] var1) {ClassLoader var2 this.getClass().getClassLoader();try {Class loaderClass Class.forName(org.springframework.boot.loader.LaunchedURLClassLoader);Class[] var4 new Class[]{URL[].class, ClassLoader.class};Constructor var5 loaderClass.getConstructor(var4);return (ClassLoader) var5.newInstance(var1, var2);} catch (Throwable var6) {}return new URLClassLoader(var1, var2);}}
8.配置文件
server:port: 8082
my:ip: 123.456.789.1三.测试
启动 Java 服务Xbootclasspath 引入 tools.jar
java -Xbootclasspath/a:C:\Progra~1\Java\jdk1.8.0_341\jre\lib\tools.jar -jar dynamic-demo.jar1.测试用类
1.测试类原类修改
package com.example.service.impl;import com.example.config.KafkaConfig;
import com.example.service.TestAbstract;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** author moon* date 2023-08-31 11:01* since 1.8*/
Component
public class TestAbstractImpl extends TestAbstract {AutowiredKafkaConfig config;Value(${my.ip})String ip;Overridepublic void hand(String str) {config.getConfig();System.out.println(How are you str);System.out.println(ip);}
}
2.测试
1.原类直接打印
http://127.0.0.1:8082/test/print?contentlisi2.原类修改
重载
http://127.0.0.1:8082/reload/re?nameTestAbstractImplbeanNametestAbstractImpl调用测试 http://127.0.0.1:8082/test/print?contentzhangsan 四.Jar 反编译记录
1.IDEA 安装插件 Java Decompiler 2.找到插件包可以将该Jar包取到其他位置使用C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2022.2\plugins\java-decompiler\lib
创建一个 SRC 目录
反编译命令%JAVA_HOME_19%\java -cp java-decompiler.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgstrue tools.jar src结果是一个 tools.jar 文件将其扩展名改为 .zip 并解压就可以看到实际已经是 java 文件了