feat: 优化编译逻辑

This commit is contained in:
wangyu 2023-09-13 14:10:35 +08:00
parent 38811b4f93
commit 96aa81d9b9
22 changed files with 262 additions and 161 deletions

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -65,4 +65,4 @@
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -2,6 +2,7 @@ package com.flyfish.framework.compiler;
import com.flyfish.framework.compiler.support.DelegateJavaCompiler; import com.flyfish.framework.compiler.support.DelegateJavaCompiler;
import com.flyfish.framework.compiler.support.SimpleJavaCompiler; import com.flyfish.framework.compiler.support.SimpleJavaCompiler;
import org.springframework.lang.Nullable;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
@ -37,7 +38,18 @@ public interface DynamicJavaCompiler extends Closeable {
* *
* @param name 文件名 * @param name 文件名
* @param source 源码 * @param source 源码
* @return 完整类名
*/
@Nullable
String compile(String name, String source) throws IOException;
/**
* 加载类
* 用于全部编译后再加载
*
* @param name 名称
* @return 结果 * @return 结果
*/ */
Class<?> compile(String name, String source) throws ClassNotFoundException, IOException; @Nullable
Class<?> load(String name);
} }

View File

@ -7,9 +7,9 @@ package com.flyfish.framework.compiler.core;
*/ */
public interface ClassLoaders { public interface ClassLoaders {
MemoryClassLoader CLASS_LOADER = new MemoryClassLoader(); DynamicClassLoader CLASS_LOADER = new MemoryClassLoader();
static MemoryClassLoader memory() { static DynamicClassLoader memory() {
return CLASS_LOADER; return CLASS_LOADER;
} }
} }

View File

@ -0,0 +1,24 @@
package com.flyfish.framework.compiler.core;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
/**
* 动态类加载器
*
* @author wangyu
*/
public abstract class DynamicClassLoader extends URLClassLoader {
DynamicClassLoader() {
super(new URL[0], DynamicClassLoader.class.getClassLoader());
}
/**
* 获取类的字节码
*
* @return 结果
*/
public abstract Map<String, byte[]> getClassBytes();
}

View File

@ -1,30 +1,31 @@
package com.flyfish.framework.compiler.core; package com.flyfish.framework.compiler.core;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import javax.tools.JavaCompiler; import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager; import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider; import javax.tools.ToolProvider;
import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.Map;
/** /**
* In-memory compile Java source code as String. * In-memory compile Java source code as String.
* *
* @author michael * @author michael
*/ */
public class JavaStringCompiler implements Closeable { @Slf4j
class JavaStringCompiler implements VendorJavaCompiler {
private final JavaCompiler compiler; private final JavaCompiler compiler;
private final MemoryJavaFileManager manager; private final MemoryJavaFileManager manager;
private final MemoryClassLoader classLoader;
public JavaStringCompiler(MemoryClassLoader classLoader) { JavaStringCompiler(DynamicClassLoader classLoader) {
this.compiler = ToolProvider.getSystemJavaCompiler(); this.compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager stdManager = compiler.getStandardFileManager(null, null, null); StandardJavaFileManager stdManager = compiler.getStandardFileManager(null, null, null);
this.manager = new MemoryJavaFileManager(stdManager, classLoader); this.manager = new MemoryJavaFileManager(stdManager, classLoader);
this.classLoader = classLoader;
} }
/** /**
@ -34,27 +35,27 @@ public class JavaStringCompiler implements Closeable {
* @param source The source code as String. * @param source The source code as String.
* @return The compiled results as Map that contains class name as key, * @return The compiled results as Map that contains class name as key,
* class binary as value. * class binary as value.
* @throws IOException If compile error.
*/ */
public Map<String, byte[]> compile(String fileName, String source) { @Override
public String compile(String fileName, String source) {
JavaFileObject javaFileObject = manager.makeStringSource(fileName, source); JavaFileObject javaFileObject = manager.makeStringSource(fileName, source);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, Collections.singletonList(javaFileObject)); JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, Collections.singletonList(javaFileObject));
Boolean result = task.call(); String className = StringUtils.substringBeforeLast(fileName, ".");
if (result == null || !result) { if (BooleanUtils.isTrue(task.call())) {
throw new RuntimeException("Compilation failed."); return manager.getClassBytes().keySet().stream().filter(key -> key.endsWith(className))
.findFirst().orElse(null);
} }
return manager.getClassBytes(); return null;
} }
/** /**
* Load class from compiled classes. * 获取动态classLoader
* *
* @param name Full class name. * @return 结果
* @return The Class instance.
* @throws ClassNotFoundException If class not found.
*/ */
public Class<?> loadClass(String name) throws ClassNotFoundException { @Override
return classLoader.loadClass(name); public DynamicClassLoader getClassLoader() {
return ClassLoaders.memory();
} }
@Override @Override
@ -63,11 +64,9 @@ public class JavaStringCompiler implements Closeable {
if (null != manager) { if (null != manager) {
manager.close(); manager.close();
} }
if (null != classLoader) { getClassLoader().close();
classLoader.close();
}
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); log.error("关闭类编译器失败!", e);
} }
} }
} }

View File

@ -2,8 +2,6 @@ package com.flyfish.framework.compiler.core;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -12,15 +10,11 @@ import java.util.concurrent.ConcurrentHashMap;
* *
* @author michael * @author michael
*/ */
class MemoryClassLoader extends URLClassLoader { class MemoryClassLoader extends DynamicClassLoader {
// class name to class bytes: // class name to class bytes:
private final Map<String, byte[]> classBytes = new ConcurrentHashMap<>(); private final Map<String, byte[]> classBytes = new ConcurrentHashMap<>();
public MemoryClassLoader() {
super(new URL[0], MemoryClassLoader.class.getClassLoader());
}
@Override @Override
protected Class<?> findClass(String name) throws ClassNotFoundException { protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] buf = classBytes.get(name); byte[] buf = classBytes.get(name);
@ -31,6 +25,7 @@ class MemoryClassLoader extends URLClassLoader {
return defineClass(name, buf); return defineClass(name, buf);
} }
@Override
public Map<String, byte[]> getClassBytes() { public Map<String, byte[]> getClassBytes() {
return classBytes; return classBytes;
} }

View File

@ -1,5 +1,7 @@
package com.flyfish.framework.compiler.core; package com.flyfish.framework.compiler.core;
import lombok.Getter;
import javax.tools.*; import javax.tools.*;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream; import java.io.FilterOutputStream;
@ -7,87 +9,82 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* In-memory java file manager. * In-memory java file manager.
* *
* @author michael * @author michael
*/ */
@Getter
class MemoryJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> { class MemoryJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> {
// compiled classes in bytes: // compiled classes in bytes:
private final Map<String, byte[]> classBytes; private final Map<String, byte[]> classBytes;
MemoryJavaFileManager(JavaFileManager fileManager, MemoryClassLoader classLoader) { MemoryJavaFileManager(JavaFileManager fileManager, DynamicClassLoader classLoader) {
super(fileManager); super(fileManager);
classBytes = classLoader.getClassBytes(); classBytes = classLoader.getClassBytes();
} }
public Map<String, byte[]> getClassBytes() { @Override
return this.classBytes; public void flush() {
} }
@Override @Override
public void flush() { public void close() throws IOException {
} classBytes.clear();
}
@Override @Override
public void close() throws IOException { public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind,
classBytes.clear(); FileObject sibling) throws IOException {
} if (kind == JavaFileObject.Kind.CLASS) {
return new MemoryOutputJavaFileObject(className);
} else {
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
@Override JavaFileObject makeStringSource(String name, String code) {
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, return new MemoryInputJavaFileObject(name, code);
FileObject sibling) throws IOException { }
if (kind == JavaFileObject.Kind.CLASS) {
return new MemoryOutputJavaFileObject(className);
} else {
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
JavaFileObject makeStringSource(String name, String code) { static class MemoryInputJavaFileObject extends SimpleJavaFileObject {
return new MemoryInputJavaFileObject(name, code);
}
static class MemoryInputJavaFileObject extends SimpleJavaFileObject { final String code;
final String code; MemoryInputJavaFileObject(String name, String code) {
super(URI.create("string:///" + name), Kind.SOURCE);
this.code = code;
}
MemoryInputJavaFileObject(String name, String code) { @Override
super(URI.create("string:///" + name), Kind.SOURCE); public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
this.code = code; return CharBuffer.wrap(code);
} }
}
@Override class MemoryOutputJavaFileObject extends SimpleJavaFileObject {
public CharBuffer getCharContent(boolean ignoreEncodingErrors) { final String name;
return CharBuffer.wrap(code);
}
}
class MemoryOutputJavaFileObject extends SimpleJavaFileObject { MemoryOutputJavaFileObject(String name) {
final String name; super(URI.create("string:///" + name), Kind.CLASS);
this.name = name;
}
MemoryOutputJavaFileObject(String name) { @Override
super(URI.create("string:///" + name), Kind.CLASS); public OutputStream openOutputStream() {
this.name = name; return new FilterOutputStream(new ByteArrayOutputStream()) {
} @Override
public void close() throws IOException {
out.close();
ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
classBytes.put(name, bos.toByteArray());
}
};
}
@Override }
public OutputStream openOutputStream() {
return new FilterOutputStream(new ByteArrayOutputStream()) {
@Override
public void close() throws IOException {
out.close();
ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
classBytes.put(name, bos.toByteArray());
}
};
}
}
} }

View File

@ -0,0 +1,31 @@
package com.flyfish.framework.compiler.core;
import java.io.Closeable;
/**
* 第三方java编译器
*
* @author wangyu
*/
public interface VendorJavaCompiler extends Closeable {
static VendorJavaCompiler string() {
return new JavaStringCompiler(ClassLoaders.memory());
}
/**
* 编译并返回编译结果
*
* @param name 文件名
* @param source 源码
* @return 完整类名
*/
String compile(String name, String source);
/**
* 获取动态classLoader
*
* @return 结果
*/
DynamicClassLoader getClassLoader();
}

View File

@ -1,21 +1,21 @@
package com.flyfish.framework.compiler.support; package com.flyfish.framework.compiler.support;
import com.flyfish.framework.compiler.DynamicJavaCompiler; import com.flyfish.framework.compiler.DynamicJavaCompiler;
import com.flyfish.framework.compiler.core.ClassLoaders; import com.flyfish.framework.compiler.core.VendorJavaCompiler;
import com.flyfish.framework.compiler.core.JavaStringCompiler; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.Map; import java.io.IOException;
/** /**
* 使用第三方成熟框架 * 使用第三方成熟框架
* *
* @author wangyu * @author wangyu
*/ */
@Slf4j
public class DelegateJavaCompiler implements DynamicJavaCompiler { public class DelegateJavaCompiler implements DynamicJavaCompiler {
// 第三方编译器 // 第三方编译器
private final JavaStringCompiler compiler = new JavaStringCompiler(ClassLoaders.memory()); private final VendorJavaCompiler compiler = VendorJavaCompiler.string();
private DelegateJavaCompiler() { private DelegateJavaCompiler() {
} }
@ -29,22 +29,32 @@ public class DelegateJavaCompiler implements DynamicJavaCompiler {
* *
* @param name 文件名 * @param name 文件名
* @param source 源码 * @param source 源码
* @return 完整类名
*/
@Override
public String compile(String name, String source) {
return compiler.compile(name, source);
}
/**
* 加载类
* 用于全部编译后再加载
*
* @param name 名称
* @return 结果 * @return 结果
*/ */
@Override @Override
public Class<?> compile(String name, String source) throws ClassNotFoundException { public Class<?> load(String name) {
Map<String, byte[]> byteMap = compiler.compile(name, source); try {
String className = StringUtils.substringBeforeLast(name, "."); return compiler.getClassLoader().loadClass(name);
for (String key : byteMap.keySet()) { } catch (ClassNotFoundException e) {
if (key.contains(className)) { log.warn("类不存在!{}", name);
return compiler.loadClass(key); return null;
}
} }
throw new RuntimeException("【java编译器】源码中没有可以编译的类");
} }
@Override @Override
public void close() { public void close() throws IOException {
compiler.close(); compiler.close();
} }
@ -52,12 +62,4 @@ public class DelegateJavaCompiler implements DynamicJavaCompiler {
private static final DelegateJavaCompiler INSTANCE = new DelegateJavaCompiler(); private static final DelegateJavaCompiler INSTANCE = new DelegateJavaCompiler();
} }
// public static void main(String[] args) throws ClassNotFoundException, IOException {
// long time = System.currentTimeMillis();
// System.out.println(StreamUtils.copyToString(DelegateJavaCompiler.class.getResourceAsStream("./"), StandardCharsets.UTF_8));
// Class<?> clazz = getInstance().compile("Fuck.java", "package com.flyfish.project; public class Fuck {}");
// System.out.println(clazz + "耗时:" + (System.currentTimeMillis() - time) / 1000.0 + "");
// }
} }

View File

@ -1,7 +1,8 @@
package com.flyfish.framework.compiler.support; package com.flyfish.framework.compiler.support;
import com.flyfish.framework.compiler.DynamicJavaCompiler; import com.flyfish.framework.compiler.DynamicJavaCompiler;
import org.springframework.util.StreamUtils; import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import javax.tools.JavaCompiler; import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager; import javax.tools.JavaFileManager;
@ -44,10 +45,10 @@ public class SimpleJavaCompiler implements DynamicJavaCompiler {
* @return 结果 * @return 结果
*/ */
@Override @Override
public Class<?> compile(String name, String source) throws ClassNotFoundException { public String compile(String name, String source) {
// 存在缓存写入 // 存在缓存写入
if (classMap.containsKey(name)) { if (classMap.containsKey(name)) {
return classMap.get(name); return classMap.get(name).getName();
} }
// 构建java文件对象 // 构建java文件对象
JavaFileObject fileObject = new StringJavaObject(name, source); JavaFileObject fileObject = new StringJavaObject(name, source);
@ -55,12 +56,32 @@ public class SimpleJavaCompiler implements DynamicJavaCompiler {
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null,
options, null, Collections.singletonList(fileObject)); options, null, Collections.singletonList(fileObject));
// 阻塞编译 // 阻塞编译
if (task.call()) { if (BooleanUtils.isTrue(task.call())) {
Class<?> clazz = Class.forName("com.flyfish.project." + name); return "com.flyfish.project." + name;
classMap.put(name, clazz); }
return clazz; return null;
}
/**
* 加载类
* 用于全部编译后再加载
*
* @param name 名称
* @return 结果
*/
@Override
public Class<?> load(String name) {
String simpleName = StringUtils.substringAfterLast(name, ".");
if (classMap.containsKey(simpleName)) {
return classMap.get(simpleName);
}
try {
Class<?> clazz = Class.forName(name);
classMap.put(clazz.getSimpleName(), clazz);
return clazz;
} catch (ClassNotFoundException e) {
return null;
} }
throw new RuntimeException("【java编译器】尝试编译源代码出现异常");
} }
@Override @Override

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -24,4 +24,4 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -46,6 +46,7 @@ class RepositoryRegistrarComposite implements RepositoryRegistrar {
@Override @Override
public void register(Class<?> clazz) { public void register(Class<?> clazz) {
if (null == clazz) return;
registrars.forEach(registrar -> registrar.register(clazz)); registrars.forEach(registrar -> registrar.register(clazz));
} }
} }

View File

@ -83,11 +83,37 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
// repo注册器 // repo注册器
RepositoryRegistrar repositoryRegistrar = RepositoryRegistrar.newInstance(metadata) RepositoryRegistrar repositoryRegistrar = RepositoryRegistrar.newInstance(metadata)
.init(metadata, resourceLoader, environment, registry, beanNameGenerator); .init(metadata, resourceLoader, environment, registry, beanNameGenerator);
// 准备注册的repo // 寻找基本包路径
Map<RestBeanCandidate, List<Class<?>>> loadedClasses = new ConcurrentHashMap<>(); String basePackage = basePackages.stream().findFirst().orElse("com.flyfish.project");
// 获取被注解的类开始编译 // 获取被注解的类开始编译
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(RestBean.class); Set<Class<?>> classes = reflections.getTypesAnnotatedWith(RestBean.class);
// 并发编译快速接入 // 并发编译快速接入准备注册的repo
Map<RestBeanCandidate, List<String>> compiledClasses = compile(basePackage, classes);
// 从repo开始注册bean
compiledClasses.getOrDefault(REPOSITORY, Collections.emptyList())
.stream()
.map(compiler::load)
.forEach(repositoryRegistrar::register);
compiledClasses.getOrDefault(SERVICE, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
compiledClasses.getOrDefault(CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
compiledClasses.getOrDefault(VIEW_CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
compiledClasses.getOrDefault(REACTIVE_VIEW_CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
log.info("结束注册rest bean...");
}
/**
* 解析并编译带注解的rest bean
*
* @param basePackage 基本路径
* @param classes 类集合
* @return 结果
*/
private Map<RestBeanCandidate, List<String>> compile(String basePackage, Set<Class<?>> classes) {
Map<RestBeanCandidate, List<String>> compiled = new ConcurrentHashMap<>();
classes.parallelStream().forEach(clazz -> { classes.parallelStream().forEach(clazz -> {
RestBean restBean = clazz.getDeclaredAnnotation(RestBean.class); RestBean restBean = clazz.getDeclaredAnnotation(RestBean.class);
if (null != restBean) { if (null != restBean) {
@ -100,7 +126,7 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
.setBeanClass(clazz.getCanonicalName()) .setBeanClass(clazz.getCanonicalName())
.setQueryBeanClass(restBean.queryClass().getCanonicalName()) .setQueryBeanClass(restBean.queryClass().getCanonicalName())
.setListViewClass(hasVo ? restBean.listViewClass().getCanonicalName() : null) .setListViewClass(hasVo ? restBean.listViewClass().getCanonicalName() : null)
.setPackageName(basePackages.stream().findFirst().orElse("com.flyfish.project")) .setPackageName(basePackage)
.setUri(makePath(clazz.getSimpleName(), restBean.value())); .setUri(makePath(clazz.getSimpleName(), restBean.value()));
// 分别生成实现类从repo到controller // 分别生成实现类从repo到controller
templates.forEach((type, template) -> { templates.forEach((type, template) -> {
@ -111,37 +137,30 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
source.setSuperClass(superClasses.getOrDefault(type, noOp).apply(restBean).getCanonicalName()); source.setSuperClass(superClasses.getOrDefault(type, noOp).apply(restBean).getCanonicalName());
source.setClassName(clazz.getSimpleName() + type.getName()); source.setClassName(clazz.getSimpleName() + type.getName());
try { try {
log.info("尝试注册{}", source.getClassName()); log.info("尝试编译{}", source.getClassName());
Class<?> compiled = compiler.compile(source.getClassName() + ".java", template.apply(source)); String className = compiler.compile(source.getClassName() + ".java", template.apply(source));
loadedClasses.computeIfAbsent(type, k -> new ArrayList<>()).add(compiled); Assert.hasText(className, "【java编译器】源码中没有可以编译的类");
// IllegalAccessException | InvocationTargetException compiled.computeIfAbsent(type, k -> new ArrayList<>()).add(className);
} catch (ClassNotFoundException | IOException e) { } catch (IOException e) {
log.error("注册{}时发生异常!", source.getClassName(), e); log.error("编译{}时发生异常!", source.getClassName(), e);
} catch (Exception e) {
log.error("编译{}警告!{}", source.getClassName(), e.getMessage());
} }
}); });
} }
}); });
// 从repo开始注册bean return compiled;
loadedClasses.getOrDefault(REPOSITORY, Collections.emptyList())
.forEach(repositoryRegistrar::register);
loadedClasses.getOrDefault(SERVICE, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
loadedClasses.getOrDefault(CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
loadedClasses.getOrDefault(VIEW_CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
loadedClasses.getOrDefault(REACTIVE_VIEW_CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
log.info("结束注册rest bean...");
} }
/** /**
* 注册bean如果是controller自动注册controller * 注册bean如果是controller自动注册controller
* *
* @param clazz class要注册的class * @param className class要注册的class
* @param registry 注册器注册bean用 * @param registry 注册器注册bean用
*/ */
private void registerBean(Class<?> clazz, BeanDefinitionRegistry registry) { private void registerBean(String className, BeanDefinitionRegistry registry) {
Class<?> clazz = compiler.load(className);
Assert.notNull(clazz, "类加载失败:" + className);
//生成BeanDefinition并注册到容器中 //生成BeanDefinition并注册到容器中
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
BeanDefinition beanDefinition = builder.getRawBeanDefinition(); BeanDefinition beanDefinition = builder.getRawBeanDefinition();

View File

@ -6,13 +6,13 @@
<groupId>com.flyfish.framework</groupId> <groupId>com.flyfish.framework</groupId>
<artifactId>flyfish-framework</artifactId> <artifactId>flyfish-framework</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.2-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.11</version> <version>2.7.14</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>