欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 動(dòng)態(tài)編譯在項(xiàng)目中的實(shí)踐分享

 更新時(shí)間:2023年07月13日 08:33:59   作者:政采云技術(shù)  
在 Java 中,動(dòng)態(tài)編譯是指在運(yùn)行時(shí)動(dòng)態(tài)地編譯 Java 源代碼,生成字節(jié)碼,并加載到 JVM 中執(zhí)行,動(dòng)態(tài)編譯可以用于實(shí)現(xiàn)動(dòng)態(tài)代碼生成、動(dòng)態(tài)加載、插件化等功能,本文將給大家分享一下Java 動(dòng)態(tài)編譯在項(xiàng)目中的實(shí)踐,感興趣的同學(xué)跟著小編一起來看看吧

1、什么是動(dòng)態(tài)編譯

在 Java 中,動(dòng)態(tài)編譯是指在運(yùn)行時(shí)動(dòng)態(tài)地編譯 Java 源代碼,生成字節(jié)碼,并加載到 JVM 中執(zhí)行。動(dòng)態(tài)編譯可以用于實(shí)現(xiàn)動(dòng)態(tài)代碼生成、動(dòng)態(tài)加載、插件化等功能。

1.1、動(dòng)態(tài)編譯的相關(guān)概念

  • JavaFileManager 對(duì)象:用于管理編譯過程中的文件。

    • JavaFileManager 是一個(gè)接口,提供了對(duì) Java 文件的管理功能,包括創(chuàng)建、查找、讀寫等操作。JavaFileManager 有多種實(shí)現(xiàn)方式,例如 StandardJavaFileManager、ForwardingJavaFileManager 等。
  • DiagnosticListener 對(duì)象:用于收集編譯時(shí)的診斷信息。

    • DiagnosticListener 是一個(gè)接口,用于接收編譯時(shí)的診斷信息,例如錯(cuò)誤、警告等。
  • JavaFileObject 對(duì)象:表示要編譯的 Java 源代碼。

    • JavaFileObject 是一個(gè)抽象類,用于表示 Java 源代碼或字節(jié)碼。JavaFileObject 有多種實(shí)現(xiàn)方式,例如 SimpleJavaFileObject、JavaFileObjectWrapper 等。

1.2、如何簡(jiǎn)單的實(shí)現(xiàn)動(dòng)態(tài)編譯

  • 創(chuàng)建一個(gè) JavaCompiler 對(duì)象,該對(duì)象用于編譯 Java 源代碼。
  • 創(chuàng)建一個(gè) DiagnosticCollector 對(duì)象,該對(duì)象用于收集編譯時(shí)的診斷信息。
  • 創(chuàng)建一個(gè) JavaFileManager 對(duì)象,該對(duì)象用于管理編譯過程中的文件。
  • 創(chuàng)建一個(gè) JavaFileObject 對(duì)象,該對(duì)象用于表示要編譯的 Java 源代碼。
  • 調(diào)用 JavaCompiler 對(duì)象的 getTask 方法,傳入 JavaFileManager 對(duì)象和 DiagnosticCollector 對(duì)象,獲取一個(gè) CompilationTask 對(duì)象。
  • 調(diào)用 CompilationTask 對(duì)象的 call 方法,編譯 Java 源代碼。
  • 獲取 DiagnosticCollector 對(duì)象的診斷信息,并處理編譯結(jié)果。

下面是一個(gè)簡(jiǎn)單的示例,演示如何使用動(dòng)態(tài)編譯:

public class DynamicCompiler {
 ? ?public static void main(String[] args) throws Exception {
 ? ? ? ?// 創(chuàng)建 JavaCompiler 對(duì)象
 ? ? ? ?JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 ? ? ? ?// 創(chuàng)建 DiagnosticCollector 對(duì)象,用于收集編譯時(shí)的診斷信息
 ? ? ? ?DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
 ? ? ? ?// 創(chuàng)建 JavaFileManager 對(duì)象,用于管理編譯過程中的文件
 ? ? ? ?StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
 ? ? ? ?// 創(chuàng)建 JavaFileObject 對(duì)象,用于表示要編譯的 Java 源代碼
 ? ? ? ?String code = "public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } }";
 ? ? ? ?JavaFileObject source = new JavaSourceFromString("HelloWorld", code);
 ? ? ? ?// 獲取 CompilationTask 對(duì)象
 ? ? ? ?Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(source);
 ? ? ? ?CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
 ? ? ? ?// 編譯 Java 源代碼
 ? ? ? ?boolean success = task.call();
 ? ? ? ?// 獲取診斷信息
 ? ? ? ?List<Diagnostic<? extends JavaFileObject>> messages = diagnostics.getDiagnostics();
 ? ? ? ?for (Diagnostic<? extends JavaFileObject> message : messages) {
 ? ? ? ? ? ?System.out.println(message.getMessage(null));
 ? ? ?  }
 ? ? ? ?// 處理編譯結(jié)果
 ? ? ? ?if (success) {
 ? ? ? ? ? ?System.out.println("Compilation was successful.");
 ? ? ?  } else {
 ? ? ? ? ? ?System.out.println("Compilation failed.");
 ? ? ?  }
 ? ? ? ?fileManager.close();
 ?  }
}
?
class JavaSourceFromString extends SimpleJavaFileObject {
 ? ?final String code;
?
 ? ?JavaSourceFromString(String name, String code) {
 ? ? ? ?super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
 ? ? ? ?this.code = code;
 ?  }
?
 ? ?@Override
 ? ?public CharSequence getCharContent(boolean ignoreEncodingErrors) {
 ? ? ? ?return code;
 ?  }
}

運(yùn)行結(jié)果:

Hello World!
Compilation was successful.

2、如何結(jié)合 springboot 項(xiàng)目使用

上面展示了如何簡(jiǎn)單使用 Java 的動(dòng)態(tài)編譯功能,但是在日常項(xiàng)目開發(fā)中,會(huì)面對(duì)更多的場(chǎng)景。結(jié)合前言中我所遇到的問題,我簡(jiǎn)單的給大家介紹下我在項(xiàng)目中是如何使用 Java 的動(dòng)態(tài)編譯功能來解決我所遇到的問題的。

我當(dāng)時(shí)的想法是這樣的:

這樣,各個(gè)業(yè)務(wù)方就可以自己管理自己的代碼塊,與外部對(duì)接或者修改代碼無需在發(fā)布應(yīng)用,徹底解放了我,讓我有更多的精力給公司做更重要的事情!

2.1、動(dòng)態(tài)編譯在項(xiàng)目中遇到的問題

2.1.1、必須重寫類加載器新編譯的代碼才能生效

在 Java 中使用動(dòng)態(tài)編譯功能時(shí),重寫類加載器是必要的。這是因?yàn)閯?dòng)態(tài)編譯生成的類需要加載到 JVM 中執(zhí)行,而默認(rèn)的類加載器無法加載動(dòng)態(tài)生成的類。

在 Java 中,類加載器分為三種:?jiǎn)?dòng)類加載器、擴(kuò)展類加載器和應(yīng)用程序類加載器。默認(rèn)情況下,Java 使用應(yīng)用程序類加載器來加載類。應(yīng)用程序類加載器只能加載預(yù)先編譯好的類,無法加載動(dòng)態(tài)生成的類。因此,我們需要重寫類加載器,使其能夠加載動(dòng)態(tài)生成的類。

重寫類加載器有兩種方式:繼承 ClassLoader 類或?qū)崿F(xiàn) ClassLoader 接口。一般情況下,我們建議使用繼承 ClassLoader 類的方式,因?yàn)檫@樣可以更方便地控制類加載的過程。

當(dāng)我們重寫類加載器時(shí),需要實(shí)現(xiàn) findClass 方法。findClass 方法用于查找指定名稱的類。如果類已經(jīng)被加載過,可以直接返回已加載的類;否則,需要使用動(dòng)態(tài)編譯生成類的字節(jié)碼,并通過 defineClass 方法將其加載到 JVM 中執(zhí)行。

2.1.2、沒有依賴的簡(jiǎn)單代碼可以編譯成功,但是一旦有依賴關(guān)系,編譯就會(huì)失敗

Java 編譯器是通過 JavaFileManager 來加載相關(guān)依賴類的,如果不重寫使用的是默認(rèn)的 JavaFileManager 來獲取 springboot 的 jarFile 來讀取嵌套 jar,自然是獲取不到的,需要我們重寫 JavaFileManager,去獲取編譯代碼所需的依賴,具體寫法詳見 2.2 代碼示例。

2.2、代碼示例

 ?// 通過調(diào)用這個(gè)方法即可實(shí)現(xiàn) java 的動(dòng)態(tài)編譯功能啦
public static Class compile(String className, String code) {
 ? ? ? ?try (MemoryClassLoader loader = MemoryClassLoader.genInstance()) {
 ? ? ? ? ? ?loader.registerJava(className, code);
 ? ? ? ? ? ?return MemoryClassLoader.getInstance().loadClass(className);
 ? ? ?  } catch (Exception e) {
 ? ? ? ? ?// ignore
 ? ? ?  }
 ?  }
}
public class MemoryClassLoader extends URLClassLoader {
?
 ? ?private static final Map<String, byte[]> classBytes = new ConcurrentHashMap<>();
?
 ? ?private MemoryClassLoader() {
 ? ? ? ?super(new URL[0], MemoryClassLoader.class.getClassLoader());
 ?  }
?
 ? ?private static final Map<String, MemoryClassLoader> CLASSLOADER_MAP = new ConcurrentHashMap<String, MemoryClassLoader>() {{
 ? ? ? ?put(KEY_CLASSLOADER, new MemoryClassLoader());
 ?  }};
?
 ? ?private static final String KEY_CLASSLOADER = "key_classloader";
?
 ? ?/**
 ? ? * 注冊(cè) Java 字符串到內(nèi)存類加載器中
 ? ? */
 ? ?public void registerJava(String className, String javaCode) {
 ? ? ? ?try {
 ? ? ? ? ? ?Map<String, byte[]> compile = compile(className, javaCode);
 ? ? ? ? ? ?if (null != compile) {
 ? ? ? ? ? ? ? ?classBytes.putAll(compile);
 ? ? ? ? ?  }
 ? ? ?  } catch (Exception e) {
 ? ? ? ? ? ?e.printStackTrace();
 ? ? ?  }
 ?  }
?
 ? ?/**
 ? ? * 編譯 Java 代碼
 ? ? */
 ? ?private static Map<String, byte[]> compile(String className, String javaCode) {
 ? ? ? ?JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 ? ? ? ?StandardJavaFileManager stdManager = getStandardFileManager(null, null, null);
 ? ? ? ?try (MemoryJavaFileManager manager = new MemoryJavaFileManager(stdManager)) {
 ? ? ? ? ? ?JavaFileObject javaFileObject = manager.makeStringSource(className, javaCode);
 ? ? ? ? ? ?JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, Collections.singletonList(javaFileObject));
 ? ? ? ? ? ?Boolean result = task.call();
 ? ? ? ? ? ?if (result != null && result) {
 ? ? ? ? ? ? ? ?return manager.getClassBytes();
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?return null;
 ?  }
?
 ? ?@Override
 ? ?public Class<?> findClass(String name) throws ClassNotFoundException {
 ? ? ? ?byte[] buf = classBytes.get(name);
 ? ? ? ?if (buf == null) {
 ? ? ? ? ? ?return super.findClass(name);
 ? ? ?  }
 ? ? ? ?return defineClass(name, buf, 0, buf.length);
 ?  }
?
 ? ?@Override
 ? ?public void close() {
 ? ? ? ?classBytes.clear();
 ? ? ? ?CLASSLOADER_MAP.clear();
 ?  }
?
 ? ?/**
 ? ? * 自定義 Java 文件管理器
 ? ? */
 ? ?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);
 ?  }
?
 ? ?/**
 ? ? * 獲取實(shí)例
 ? ? */
 ? ?public static MemoryClassLoader getInstance() {
 ? ? ? ?return CLASSLOADER_MAP.get(KEY_CLASSLOADER);
 ?  }
?
 ? ?/**
 ? ? * 生成新的實(shí)例
 ? ? */
 ? ?public static MemoryClassLoader genInstance() {
 ? ? ? ?MemoryClassLoader classLoader = new MemoryClassLoader();
 ? ? ? ?CLASSLOADER_MAP.put(KEY_CLASSLOADER, new MemoryClassLoader());
 ? ? ? ?return classLoader;
 ?  }
?
 ? ?public static String getPath() {
 ? ? ? ?ApplicationHome home = new ApplicationHome(MemoryJavaFileManager.class);
 ? ? ? ?String path = home.getSource().getPath();
 ? ? ? ?return path;
 ?  }
?
 ? ?public static boolean isJar() {
 ? ? ? ?return getPath().endsWith(".jar");
 ?  }
?
}
class MemoryJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> {
?
 ? ?// compiled classes in bytes:
 ? ?final Map<String, byte[]> classBytes = new HashMap<>();
?
 ? ?final Map<String, List<JavaFileObject>> classObjectPackageMap = new HashMap<>();
?
 ? ?private JavacFileManager javaFileManager;
?
 ? ?/**
 ? ? * key 包名 value javaobj 主要給 jdk 編譯 class 的時(shí)候找依賴 class 用
 ? ? */
 ? ?public final static Map<String, List<JavaFileObject>> CLASS_OBJECT_PACKAGE_MAP = new HashMap<>();
?
 ? ?private static final Object lock = new Object();
?
 ? ?private boolean isInit = false;
?
 ? ?public void init() {
 ? ? ? ?try {
 ? ? ? ? ? ?String jarBaseFile = MemoryClassLoader.getPath();
 ? ? ? ? ? ?JarFile jarFile = new JarFile(new File(jarBaseFile));
 ? ? ? ? ? ?List<JarEntry> entries = jarFile.stream().filter(jarEntry -> jarEntry.getName().endsWith(".jar")).collect(Collectors.toList());
 ? ? ? ? ? ?JarFile libTempJarFile;
 ? ? ? ? ? ?List<JavaFileObject> onePackageJavaFiles;
 ? ? ? ? ? ?String packageName;
 ? ? ? ? ? ?for (JarEntry entry : entries) {
 ? ? ? ? ? ? ? ?libTempJarFile = jarFile.getNestedJarFile(jarFile.getEntry(entry.getName()));
 ? ? ? ? ? ? ? ?if (libTempJarFile.getName().contains("tools.jar")) {
 ? ? ? ? ? ? ? ? ? ?continue;
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ?Enumeration<JarEntry> tempEntriesEnum = libTempJarFile.entries();
 ? ? ? ? ? ? ? ?while (tempEntriesEnum.hasMoreElements()) {
 ? ? ? ? ? ? ? ? ? ?JarEntry jarEntry = tempEntriesEnum.nextElement();
 ? ? ? ? ? ? ? ? ? ?String classPath = jarEntry.getName().replace("/", ".");
 ? ? ? ? ? ? ? ? ? ?if (!classPath.endsWith(".class") || jarEntry.getName().lastIndexOf("/") == -1) {
 ? ? ? ? ? ? ? ? ? ? ? ?continue;
 ? ? ? ? ? ? ? ? ?  } else {
 ? ? ? ? ? ? ? ? ? ? ? ?packageName = classPath.substring(0, jarEntry.getName().lastIndexOf("/"));
 ? ? ? ? ? ? ? ? ? ? ? ?onePackageJavaFiles = CLASS_OBJECT_PACKAGE_MAP.containsKey(packageName) ? CLASS_OBJECT_PACKAGE_MAP.get(packageName) : new ArrayList<>();
 ? ? ? ? ? ? ? ? ? ? ? ?onePackageJavaFiles.add(new MemorySpringBootInfoJavaClassObject(jarEntry.getName().replace("/", ".").replace(".class", ""),
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?new URL(libTempJarFile.getUrl(), jarEntry.getName()), javaFileManager));
 ? ? ? ? ? ? ? ? ? ? ? ?CLASS_OBJECT_PACKAGE_MAP.put(packageName, onePackageJavaFiles);
 ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  } catch (Exception e) {
 ? ? ? ? ? ?e.printStackTrace();
 ? ? ?  }
 ? ? ? ?isInit = true;
?
 ?  }
?
 ? ?MemoryJavaFileManager(JavaFileManager fileManager) {
 ? ? ? ?super(fileManager);
 ? ? ? ?this.javaFileManager = (JavacFileManager) fileManager;
 ?  }
?
 ? ?public Map<String, byte[]> getClassBytes() {
 ? ? ? ?return new HashMap<>(this.classBytes);
 ?  }
?
 ? ?@Override
 ? ?public void flush() {
 ?  }
?
 ? ?@Override
 ? ?public void close() {
 ? ? ? ?classBytes.clear();
 ? ? ? ?classObjectPackageMap.clear();
 ? ? ? ?CLASS_OBJECT_PACKAGE_MAP.clear();
 ?  }
?
?
 ? ?public List<JavaFileObject> getLibJarsOptions(String packgeName) {
 ? ? ? ?synchronized (lock) {
 ? ? ? ? ? ?if (!isInit) {
 ? ? ? ? ? ? ? ?init();
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?return CLASS_OBJECT_PACKAGE_MAP.get(packgeName);
 ?  }
?
 ? ?@Override
 ? ?public Iterable<JavaFileObject> list(Location location,String packageName, Set<JavaFileObject.Kind> kinds,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? boolean recurse) throws IOException {
 ? ? ? ?if ("CLASS_PATH".equals(location.getName()) && MemoryClassLoader.isJar()) {
 ? ? ? ? ? ?List<JavaFileObject> result = getLibJarsOptions(packageName);
 ? ? ? ? ? ?if (result != null) {
 ? ? ? ? ? ? ? ?return result;
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?Iterable<JavaFileObject> it = super.list(location, packageName, kinds, recurse);
 ? ? ? ?if (kinds.contains(JavaFileObject.Kind.CLASS)) {
 ? ? ? ? ? ?final List<JavaFileObject> 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;
 ? ? ?  }
 ?  }
?
 ? ?@Override
 ? ?public String inferBinaryName(Location location, JavaFileObject file) {
 ? ? ? ?if (file instanceof MemoryInputJavaClassObject) {
 ? ? ? ? ? ?return ((MemoryInputJavaClassObject) file).inferBinaryName();
 ? ? ?  }
 ? ? ? ?return super.inferBinaryName(location, file);
 ?  }
?
 ? ?@Override
 ? ?public 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);
 ? ? ?  }
 ?  }
?
 ? ?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) {
 ? ? ? ? ? ?@Override
 ? ? ? ? ? ?public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
 ? ? ? ? ? ? ? ?return CharBuffer.wrap(code);
 ? ? ? ? ?  }
 ? ? ?  };
 ?  }
?
 ? ?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);
 ? ? ?  }
 ? ? ? ?List<JavaFileObject> 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;
 ? ? ?  }
?
 ? ? ? ?@Override
 ? ? ? ?public 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;
 ? ? ?  }
 ? ? ? ?@Override
 ? ? ? ?public OutputStream openOutputStream() {
 ? ? ? ? ? ?return new FilterOutputStream(new ByteArrayOutputStream()) {
 ? ? ? ? ? ? ? ?@Override
 ? ? ? ? ? ? ? ?public void close() throws IOException {
 ? ? ? ? ? ? ? ? ? ?out.close();
 ? ? ? ? ? ? ? ? ? ?ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
 ? ? ? ? ? ? ? ? ? ?byte[] bs = bos.toByteArray();
 ? ? ? ? ? ? ? ? ? ?classBytes.put(className, bs);
 ? ? ? ? ? ? ? ? ? ?makeBinaryClass(className, bs);
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  };
 ? ? ?  }
 ?  }
}
?
class MemorySpringBootInfoJavaClassObject extends BaseFileObject {
 ? ?private final String className;
 ? ?private URL url;
?
 ? ?MemorySpringBootInfoJavaClassObject(String className, URL url, JavacFileManager javacFileManager) {
 ? ? ? ?super(javacFileManager);
 ? ? ? ?this.className = className;
 ? ? ? ?this.url = url;
 ?  }
?
 ? ?@Override
 ? ?public Kind getKind() {
 ? ? ? ?return Kind.valueOf("CLASS");
 ?  }
?
 ? ?@Override
 ? ?public URI toUri() {
 ? ? ? ?try {
 ? ? ? ? ? ?return url.toURI();
 ? ? ?  } catch (URISyntaxException e) {
 ? ? ? ? ? ?e.printStackTrace();
 ? ? ?  }
 ? ? ? ?return null;
 ?  }
?
 ? ?@Override
 ? ?public String getName() {
 ? ? ? ?return className;
 ?  }
?
 ? ?@Override
 ? ?public InputStream openInputStream() {
 ? ? ? ?try {
 ? ? ? ? ? ?return url.openStream();
 ? ? ?  } catch (IOException e) {
 ? ? ? ? ? ?e.printStackTrace();
 ? ? ?  }
 ? ? ? ?return null;
 ?  }
?
 ? ?@Override
 ? ?public OutputStream openOutputStream() throws IOException {
 ? ? ? ?return null;
 ?  }
?
 ? ?@Override
 ? ?public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
 ? ? ? ?return null;
 ?  }
?
 ? ?@Override
 ? ?public Writer openWriter() throws IOException {
 ? ? ? ?return null;
 ?  }
 ? ?@Override
 ? ?public long getLastModified() {
 ? ? ? ?return 0;
 ?  }
?
 ? ?@Override
 ? ?public boolean delete() {
 ? ? ? ?return false;
 ?  }
?
 ? ?@Override
 ? ?public String getShortName() {
 ? ? ? ?return className.substring(className.lastIndexOf("."));
 ?  }
 ? ?@Override
 ? ?protected String inferBinaryName(Iterable<? extends File> iterable) {
 ? ? ? ?return className;
 ?  }
?
 ? ?@Override
 ? ?public boolean equals(Object o) {
 ? ? ? ?return false;
 ?  }
?
 ? ?@Override
 ? ?public int hashCode() {
 ? ? ? ?return 0;
 ?  }
?
 ? ?@Override
 ? ?public boolean isNameCompatible(String simpleName, Kind kind) {
 ? ? ? ?return false;
 ?  }
}
?
// 自定義 springboot 的類加載器
class SpringJavaFileManager extends JavacFileManager {
 ? ?public SpringJavaFileManager(Context context, boolean b, Charset charset) {
 ? ? ? ?super(context, b, charset);
 ?  }
?
 ? ?@Override
 ? ?public 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()]));
 ? ? ?  }
 ?  }
?
 ? ?protected 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);
 ?  }
}

總結(jié)

動(dòng)態(tài)編譯可能在日常工作中所使用的場(chǎng)景不多,但在特定的場(chǎng)景下能夠很好的解決我們所遇到的問題,本篇文章可以給大家提供一些視野,當(dāng)你遇到類似場(chǎng)景時(shí)或許動(dòng)態(tài)編譯能夠很好的解決它!

最后希望大家都能在自己平凡的工作里從編程中收獲一些快樂~

到此這篇關(guān)于Java 動(dòng)態(tài)編譯在項(xiàng)目中的實(shí)踐分享的文章就介紹到這了,更多相關(guān)Java 動(dòng)態(tài)編譯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?實(shí)現(xiàn)字符串SHA1加密方法

    Java?實(shí)現(xiàn)字符串SHA1加密方法

    這篇文章主要介紹了Java?實(shí)現(xiàn)字符串SHA1加密方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot中Elasticsearch的連接配置原理與使用詳解

    SpringBoot中Elasticsearch的連接配置原理與使用詳解

    Elasticsearch是一種開源的分布式搜索和數(shù)據(jù)分析引擎,它可用于全文搜索、結(jié)構(gòu)化搜索、分析等應(yīng)用場(chǎng)景,本文主要介紹了SpringBoot中Elasticsearch的連接配置原理與使用詳解,感興趣的可以了解一下
    2023-09-09
  • 剖析Spring WebFlux反應(yīng)式編程設(shè)計(jì)及工作原理

    剖析Spring WebFlux反應(yīng)式編程設(shè)計(jì)及工作原理

    這篇文章主要為大家介紹了Spring WebFlux反應(yīng)式編程模型工作原理的剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-02-02
  • 2020JDK1.8安裝教程詳解(一次就可安裝成功)

    2020JDK1.8安裝教程詳解(一次就可安裝成功)

    這篇文章主要介紹了2020JDK1.8安裝教程詳解(一次就可安裝成功),本文通過圖文并茂的形式分步驟給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-08-08
  • SpringBoot自定義starter啟動(dòng)器的實(shí)現(xiàn)思路

    SpringBoot自定義starter啟動(dòng)器的實(shí)現(xiàn)思路

    這篇文章主要介紹了SpringBoot如何自定義starter啟動(dòng)器,通過starter的自定義過程,能夠加深大家對(duì)SpringBoot自動(dòng)配置原理的理解,需要的朋友可以參考下
    2022-10-10
  • 一文掌握Spring的創(chuàng)建與使用

    一文掌握Spring的創(chuàng)建與使用

    這篇文章詳細(xì)介紹了spring的創(chuàng)建與使用,文章中有詳細(xì)的代碼示例和圖片介紹,對(duì)學(xué)習(xí)有一定的而參考價(jià)值,需要的同學(xué)可以參考一下
    2023-04-04
  • 一文讓你搞懂如何手寫一個(gè)redis分布式鎖

    一文讓你搞懂如何手寫一個(gè)redis分布式鎖

    既然要搞懂Redis分布式鎖,那肯定要有一個(gè)需要它的場(chǎng)景。高并發(fā)售票問題就是一個(gè)經(jīng)典案例。本文就來利用這個(gè)場(chǎng)景手寫一個(gè)redis分布式鎖,讓你徹底搞懂它
    2022-11-11
  • Maven 主模塊和子模塊pom.xml依賴聲明

    Maven 主模塊和子模塊pom.xml依賴聲明

    這篇文章主要介紹了Maven 主模塊和子模塊pom.xml依賴聲明,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java基礎(chǔ)之容器LinkedList

    Java基礎(chǔ)之容器LinkedList

    這篇文章主要介紹了Java基礎(chǔ)之容器LinkedList,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • SpringMVC實(shí)現(xiàn)注解式權(quán)限驗(yàn)證的實(shí)例

    SpringMVC實(shí)現(xiàn)注解式權(quán)限驗(yàn)證的實(shí)例

    本篇文章主要介紹了SpringMVC實(shí)現(xiàn)注解式權(quán)限驗(yàn)證的實(shí)例,可以使用Spring MVC中的action攔截器來實(shí)現(xiàn),具有一定的參考價(jià)值,有興趣的可以了解下。
    2017-02-02

最新評(píng)論