Я пытаюсь сгенерировать группу классов модели динамически во время выполнения, используя конфигурацию, определенную в файле yaml.
Я в значительной степени могу генерировать файлы, но проблема возникает, скажем, для пример: существует 2 класса: класс A и B, класс B имеет объект класса A (имеет ассоциацию). Code будет динамически создавать исходный код для класса и загружать его с помощью загрузчика классов. Теперь, когда мой код пытается загрузить класс B после генерации кода, я получаю сообщение об ошибке «Невозможно найти символ».
Yaml, который работает:
A:
field1: String
field2:
type: Map
keys: String
values: String
B:
field1: String
field2: String
Yaml, который не работает:
A:
field1: String
field2:
type: Map
keys: String
values: String
B:
field1: String
field2:
type: List
items: A
Парсер Yaml:
public class YamlParser {
public static Map parseYaml(String yamlFilePath) {
Yaml yaml = new Yaml(new Constructor(Map.class));
try (InputStream inputStream = YamlParser.class.getClassLoader().getResourceAsStream(yamlFilePath)) {
return yaml.load(inputStream);
} catch (Exception e) {
throw new RuntimeException("Failed to parse YAML file", e);
}
}
}
Основная функция:
public static void main(String[] args) {
Map yamlData = YamlParser.parseYaml("models.yaml");
yamlData.forEach((className, fields) -> {
Class generatedClass = null;
try {
generatedClass = new DynamicClassGenerator().generateClass(className, (Map) fields);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("Generated class: " + generatedClass.getName());
});
}
DynamicClassGenerator:
public class DynamicClassGenerator {
private static final Map generateClass(String className, Map fields) throws IOException {
if (generatedClasses.containsKey(className)) {
return generatedClasses.get(className);
}
String code = generateCode(className, fields);
File sourceFile = saveCodeToFile(code, className, tmpDirectory);
compileCode(sourceFile);
Class loadedClass = loadCompiledCode(className);
generatedClasses.put(className, loadedClass);
return loadedClass;
}
private static Class loadCompiledCode(String className) {
try {
Class loadedClass = Class.forName("org.example.parser." + className, true, classLoader);
Object instance = loadedClass.getDeclaredConstructor().newInstance();
System.out.println(instance);
return loadedClass;
} catch (Exception e) {
throw new RuntimeException("Failed to load compiled code", e);
}
}
private static void compileCode(File sourceFile) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());
}
private static File saveCodeToFile(String code, String fileName, File root) throws IOException {
File sourceFile = new File(root, "org/example/parser/" + fileName + ".java");
if (dirDoesNotExists(sourceFile)) {
sourceFile.getParentFile().mkdirs();
}
Files.writeString(sourceFile.toPath(), code);
return sourceFile;
}
private static boolean dirDoesNotExists(File sourceFile) {
return !sourceFile.getParentFile().exists();
}
private static String generateCode(String className, Map fields) {
StringBuilder classBuilder = new StringBuilder();
classBuilder.append("package org.example.parser;\n");
classBuilder.append("\n");
classBuilder.append("import org.example.model.BaseEntity;\n");
classBuilder.append("import java.util.List;\n");
classBuilder.append("import java.util.Map;\n");
classBuilder.append("\n");
classBuilder.append("public class ").append(className).append(" extends BaseEntity {\n");
fields.forEach((fieldName, fieldType) -> {
if (fieldType instanceof Map) {
Map typeMap = (Map) fieldType;
String type = (String) typeMap.get("type");
if ("List".equals(type)) {
String items = (String) typeMap.get("items");
classBuilder.append("private List ").append(fieldName).append(";\n");
} else if ("Map".equals(type)) {
String key = (String) typeMap.get("keys");
String value = (String) typeMap.get("values");
classBuilder.append("private Map ").append(fieldName).append(";\n");
}
} else {
classBuilder.append("private ").append(fieldType).append(" ").append(fieldName).append(";\n");
}
});
classBuilder.append("}");
return classBuilder.toString();
}
}
Подробнее здесь: https://stackoverflow.com/questions/788 ... to-another
Импортируйте класс, созданный во время выполнения, как зависимость в другой. ⇐ JAVA
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение