diff --git a/autil-incubator/incubator-annotation/pom.xml b/autil-incubator/incubator-annotation/pom.xml
index d4aa8ae..f0c7a04 100644
--- a/autil-incubator/incubator-annotation/pom.xml
+++ b/autil-incubator/incubator-annotation/pom.xml
@@ -9,17 +9,17 @@
com.acanx.util
incubator-annotation
- 0.2.0.0-SNAPSHOT
+ 0.4.3-SNAPSHOT
jar
Incubator-Annotation
AUtil Incubator Annotation Module
https://acanx.com
- 11
+ 21
UTF-8
- 11
- 3.14.0
+ false
+ 3.14.1
@@ -28,42 +28,23 @@
javapoet
1.13.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
com.acanx.util
autil-core
${revision}
-
-
-
-
-
-
org.junit.jupiter
junit-jupiter-api
${junit-jupiter.version}
test
+
+
+
+
+
+
@@ -81,14 +62,38 @@
${java.version}
${java.version}
-
-
-
- com.acanx.util
- incubator-annotation
- 0.2.0.0-SNAPSHOT
-
-
+ UTF-8
+ false
+
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+
+
+ --add-opens=jdk.compiler/com.sun.tools.javac.util=com.acanx.util.incubator.annotation
+
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+ -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+
+
+
+
+
+
+
+
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/ASTScanner.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/ASTScanner.java
deleted file mode 100644
index f44eba7..0000000
--- a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/ASTScanner.java
+++ /dev/null
@@ -1,301 +0,0 @@
-package com.acanx.util.incubator.annotation;//package com.acanx.util.object.copy;
-//
-//import com.sun.tools.javac.code.Symbol;
-//import com.sun.tools.javac.code.Type;
-//import com.sun.tools.javac.model.JavacElements;
-//import com.sun.tools.javac.tree.JCTree;
-//import com.sun.tools.javac.tree.TreeMaker;
-//import com.sun.tools.javac.tree.TreeScanner;
-//import com.sun.tools.javac.util.List;
-//import com.sun.tools.javac.util.Names;
-//
-//import javax.lang.model.element.ElementKind;
-//import java.util.Arrays;
-//import java.util.HashMap;
-//import java.util.HashSet;
-//import java.util.Map;
-//import java.util.Set;
-//
-///**
-// * ASTScanner
-// *
-// * @author ACANX
-// * @date 2025-06-14
-// * @since 202506
-// */
-//public class ASTScanner extends TreeScanner {
-// private final TreeMaker maker;
-// private final JavacElements elements;
-// private final Names names;
-//
-// ASTScanner(TreeMaker maker, JavacElements elements, Names names) {
-// this.maker = maker;
-// this.elements = elements;
-// this.names = names;
-// }
-// // JDK 8 兼容方法
-// @SuppressWarnings("unused")
-// public void scan(JCTree tree, Void ignored) {
-// if (tree != null) {
-// tree.accept(this);
-// }
-// }
-//
-// // JDK 11 兼容的扫描方法
-// @Override
-// public void visitTopLevel(JCTree.JCCompilationUnit tree) {
-// super.visitTopLevel(tree);
-// // 扫描顶级元素
-// for (JCTree def : tree.defs) {
-// if (def instanceof JCTree.JCClassDecl) {
-// visitClassDef((JCTree.JCClassDecl) def);
-// }
-// }
-// }
-//
-// @Override
-// public void visitClassDef(JCTree.JCClassDecl tree) {
-// super.visitClassDef(tree);
-// // 扫描类中的所有方法
-// for (JCTree member : tree.defs) {
-// if (member instanceof JCTree.JCMethodDecl) {
-// processMethod((JCTree.JCMethodDecl) member);
-// }
-// }
-// }
-//
-// private void processMethod(JCTree.JCMethodDecl method) {
-// // 获取方法上的所有MetaObjectCopy注解
-// List annotations = getMetaObjectCopyAnnotations(method);
-// if (!annotations.isEmpty()) {
-// // 合并所有注解配置
-// boolean copyNulls = annotations.stream().anyMatch(MetaObjectCopy::copyNulls);
-// Set ignoreFields = new HashSet<>();
-// Map fieldMappings = new HashMap<>();
-// for (MetaObjectCopy ann : annotations) {
-// ignoreFields.addAll(Arrays.asList(ann.ignoreFields()));
-// for (MetaObjectCopy.FieldMapping mapping : ann.fieldMappings()) {
-// fieldMappings.put(mapping.target(), mapping.source());
-// }
-// }
-// // 替换方法体
-// method.body = createMethodBody(
-// method.params.get(0),
-// method.params.get(1),
-// copyNulls,
-// ignoreFields,
-// fieldMappings
-// );
-// }
-// }
-//
-// private List getMetaObjectCopyAnnotations(JCTree.JCMethodDecl method) {
-// List annotations = List.nil();
-// for (JCTree.JCAnnotation ann : method.mods.annotations) {
-// Type type = ann.type;
-// if (type != null) {
-// String annotationName = type.toString();
-// if (annotationName.equals(MetaObjectCopy.class.getName())) {
-// // 解析注解属性
-// annotations.add(parseAnnotation(ann));
-// } else if (annotationName.equals(MetaObjectCopy.List.class.getName())) {
-// // 处理多个注解
-// for (JCTree.JCExpression expr : ann.args) {
-// if (expr instanceof JCTree.JCAnnotation) {
-// annotations.add(parseAnnotation((JCTree.JCAnnotation) expr));
-// }
-// }
-// }
-// }
-// }
-// return annotations;
-// }
-//
-// private MetaObjectCopy parseAnnotation(JCTree.JCAnnotation ann) {
-// // 简化处理 - 实际应解析所有属性
-// return new MetaObjectCopy() {
-// @Override
-// public boolean copyNulls() {
-// return false; // 简化实现
-// }
-//
-// @Override
-// public String[] ignoreFields() {
-// return new String[0]; // 简化实现
-// }
-//
-// @Override
-// public FieldMapping[] fieldMappings() {
-// return new FieldMapping[0]; // 简化实现
-// }
-//
-// @Override
-// public Class extends java.lang.annotation.Annotation> annotationType() {
-// return MetaObjectCopy.class;
-// }
-// };
-// }
-//
-// private JCTree.JCBlock createMethodBody(
-// JCTree.JCVariableDecl sourceParam,
-// JCTree.JCVariableDecl targetParam,
-// boolean copyNulls,
-// Set ignoreFields,
-// Map fieldMappings
-// ) {
-// List statements = com.sun.tools.javac.util.List.nil();
-//
-// // 1. 空值检查
-// statements = statements.append(createNullCheck(sourceParam, targetParam));
-// // 2. 获取源和目标类型
-// Symbol.ClassSymbol sourceType = (Symbol.ClassSymbol) sourceParam.vartype.type.tsym;
-// Symbol.ClassSymbol targetType = (Symbol.ClassSymbol) targetParam.vartype.type.tsym;
-// // 3. 生成字段拷贝语句
-// statements = statements.appendList(createFieldCopyStatements(
-// sourceParam,
-// targetParam,
-// sourceType,
-// targetType,
-// copyNulls,
-// ignoreFields,
-// fieldMappings
-// ));
-// return maker.Block(0, statements);
-// }
-//
-// private JCTree.JCStatement createNullCheck(JCTree.JCVariableDecl source, JCTree.JCVariableDecl target) {
-// // if (source == null || target == null) return;
-// return maker.If(
-// maker.Binary(
-// JCTree.Tag.OR,
-// maker.Binary(
-// JCTree.Tag.EQ,
-// maker.Ident(source.name),
-// maker.Literal(null)
-// ),
-// maker.Binary(
-// JCTree.Tag.EQ,
-// maker.Ident(target.name),
-// maker.Literal(null)
-// )
-// ),
-// maker.Block(0, List.of(maker.Return(null))),
-// null
-// );
-// }
-//
-// private List createFieldCopyStatements(
-// JCTree.JCVariableDecl sourceParam,
-// JCTree.JCVariableDecl targetParam,
-// Symbol.ClassSymbol sourceType,
-// Symbol.ClassSymbol targetType,
-// boolean copyNulls,
-// Set ignoreFields,
-// Map fieldMappings) {
-// List statements = com.sun.tools.javac.util.List.nil();
-// // 获取目标字段列表
-// Map targetFields = getAccessibleFields(targetType);
-// for (Map.Entry entry : targetFields.entrySet()) {
-// String targetFieldName = entry.getKey();
-// Symbol.VarSymbol targetField = entry.getValue();
-// // 检查是否忽略该字段
-// if (ignoreFields.contains(targetFieldName)) {
-// continue;
-// }
-// // 获取源字段名(考虑自定义映射)
-// String sourceFieldName = fieldMappings.getOrDefault(targetFieldName, targetFieldName);
-// // 获取源字段
-// Symbol.VarSymbol sourceField = getField(sourceType, sourceFieldName);
-// if (sourceField == null) {
-// continue; // 源对象没有该字段
-// }
-// // 生成字段拷贝语句
-// JCTree.JCStatement copyStmt = createSingleFieldCopy(
-// sourceParam,
-// targetParam,
-// sourceField,
-// targetField,
-// copyNulls
-// );
-// if (copyStmt != null) {
-// statements = statements.append(copyStmt);
-// }
-// }
-// return statements;
-// }
-//
-// private Map getAccessibleFields(Symbol.ClassSymbol clazz) {
-// Map fields = new HashMap<>();
-// // 获取所有字段(包括继承的)
-// for (Symbol member : elements.getAllMembers(clazz)) {
-// if (member.getKind().equals(ElementKind.FIELD)){
-// Symbol.VarSymbol field = (Symbol.VarSymbol) member;
-// fields.put(field.getSimpleName().toString(), field);
-// }
-// }
-// return fields;
-// }
-//
-// private Symbol.VarSymbol getField(Symbol.ClassSymbol clazz, String fieldName) {
-// for (Symbol member : elements.getAllMembers(clazz)) {
-// if (member.getKind().equals(ElementKind.FIELD) &&
-// member.getSimpleName().toString().equals(fieldName)) {
-// return (Symbol.VarSymbol) member;
-// }
-// }
-// return null;
-// }
-//
-// private JCTree.JCStatement createSingleFieldCopy(
-// JCTree.JCVariableDecl sourceParam,
-// JCTree.JCVariableDecl targetParam,
-// Symbol.VarSymbol sourceField,
-// Symbol.VarSymbol targetField,
-// boolean copyNulls) {
-// try {
-// // 1. 构建getter调用
-// String getterName = getAccessorName(sourceField.getSimpleName().toString(), "get");
-// JCTree.JCExpression getterCall = maker.Apply(
-// com.sun.tools.javac.util.List.nil(),
-// maker.Select(maker.Ident(sourceParam.name), names.fromString(getterName)),
-// com.sun.tools.javac.util.List.nil()
-// );
-// // 2. 构建setter调用
-// String setterName = getAccessorName(targetField.getSimpleName().toString(), "set");
-// JCTree.JCExpression setterCall = maker.Apply(
-// com.sun.tools.javac.util.List.nil(),
-// maker.Select(maker.Ident(targetParam.name), names.fromString(setterName)),
-// List.of(getterCall)
-// );
-// // 3. 基本类型直接赋值
-// if (targetField.type.isPrimitive()) {
-// return maker.Exec(setterCall);
-// }
-// // 4. 非基本类型处理
-// if (copyNulls) {
-// // 允许空值 - 直接赋值
-// return maker.Exec(setterCall);
-// } else {
-// // 不允许空值 - 添加空值检查
-// JCTree.JCExpression notNullCheck = maker.Binary(
-// JCTree.Tag.NE,
-// getterCall,
-// maker.Literal(null)
-// );
-// return maker.If(
-// notNullCheck,
-// maker.Exec(setterCall),
-// null
-// );
-// }
-// } catch (Exception e) {
-// // getter/setter不存在
-// return null;
-// }
-// }
-//
-// private String getAccessorName(String fieldName, String prefix) {
-// return prefix + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
-// }
-//}
-//
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/App.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/App.java
deleted file mode 100644
index 3586920..0000000
--- a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/App.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.acanx.util.incubator.annotation;
-
-/**
- *
- * App
- *
- */
-public class App {
- public static void main(String[] args) {
- System.out.println("Hello World!");
- }
-}
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/Copier.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/Copier.java
new file mode 100644
index 0000000..6f5b1f1
--- /dev/null
+++ b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/Copier.java
@@ -0,0 +1,54 @@
+package com.acanx.util.incubator.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 对象拷贝注解,用于标记需要进行编译期增强的对象拷贝方法
+ * 被注解的方法会在编译期被增强,自动实现从第一个参数到第二个参数的对象拷贝
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.SOURCE)
+public @interface Copier {
+
+ /**
+ * 拷贝策略,默认为浅拷贝
+ */
+ CopyStrategy strategy() default CopyStrategy.SHALLOW;
+
+ /**
+ * 是否忽略空值,如果为true则源对象为null的字段不会覆盖目标对象的字段
+ */
+ boolean ignoreNull() default false;
+
+ /**
+ * 需要排除的字段名列表
+ */
+ String[] exclude() default {};
+
+ /**
+ * 仅包含的字段名列表,如果设置了则只拷贝这些字段
+ */
+ String[] include() default {};
+
+ /**
+ * 是否使用getter/setter方法进行拷贝
+ *
+ * @return
+ */
+ boolean useAccessors () default true;
+
+ /**
+ * 拷贝策略枚举
+ */
+ enum CopyStrategy {
+ /** 浅拷贝,直接赋值 */
+ SHALLOW,
+ /** 深拷贝,对引用类型创建新对象 */
+ DEEP
+ }
+
+
+}
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/CopierProcessor.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/CopierProcessor.java
new file mode 100644
index 0000000..91fc03a
--- /dev/null
+++ b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/CopierProcessor.java
@@ -0,0 +1,416 @@
+package com.acanx.util.incubator.annotation;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@SupportedAnnotationTypes("com.acanx.util.incubator.annotation.Copier")
+@SupportedSourceVersion(SourceVersion.RELEASE_17)
+public class CopierProcessor extends AbstractProcessor {
+
+ private Types typeUtils;
+ private Elements elementUtils;
+ private Filer filer;
+
+ @Override
+ public synchronized void init(javax.annotation.processing.ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ typeUtils = processingEnv.getTypeUtils();
+ elementUtils = processingEnv.getElementUtils();
+ filer = processingEnv.getFiler();
+ }
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver()) {
+ return false;
+ }
+
+ note("开始处理 @ObjectCopier 注解", null);
+
+ // 按被注解方法所在的类进行分组
+ Map> classMethodsMap = new HashMap<>();
+ for (Element element : roundEnv.getElementsAnnotatedWith(Copier.class)) {
+ if (element.getKind() != ElementKind.METHOD) {
+ error("注解@ObjectCopier只能应用于方法", element, getAnnotationMirror(element));
+ continue;
+ }
+ ExecutableElement method = (ExecutableElement) element;
+ TypeElement enclosingClass = (TypeElement) method.getEnclosingElement();
+ classMethodsMap.computeIfAbsent(enclosingClass, k -> new ArrayList<>()).add(method);
+
+ note("找到被注解的方法: " + enclosingClass.getSimpleName() + "." + method.getSimpleName(), method);
+ }
+
+ // 为每个包含被注解方法的类生成一个拷贝类
+ for (Map.Entry> entry : classMethodsMap.entrySet()) {
+ TypeElement enclosingClass = entry.getKey();
+ List methods = entry.getValue();
+ try {
+ generateCopierClass(enclosingClass, methods);
+ } catch (Exception e) {
+ error("生成拷贝类时出错: " + e.getMessage(), enclosingClass, null);
+ }
+ }
+
+ note("注解处理完成", null);
+ return true;
+ }
+
+ private void generateCopierClass(TypeElement enclosingClass, List methods) throws IOException {
+ // 验证所有方法
+ List validMethods = new ArrayList<>();
+ for (ExecutableElement method : methods) {
+ if (validateMethod(method)) {
+ validMethods.add(method);
+ }
+ }
+
+ if (validMethods.isEmpty()) {
+ return;
+ }
+
+ // 生成类名:使用被注解方法所在类的类名 + "Copier"
+ String enclosingClassName = enclosingClass.getSimpleName().toString();
+ String copierClassName = enclosingClassName + "Copier";
+
+ // 获取包名
+ String packageName = elementUtils.getPackageOf(enclosingClass).getQualifiedName().toString();
+
+ // 创建源文件
+ JavaFileObject builderFile = filer.createSourceFile(
+ packageName + "." + copierClassName,
+ enclosingClass
+ );
+
+ note("生成拷贝类: " + packageName + "." + copierClassName + ",包含 " + validMethods.size() + " 个方法", enclosingClass);
+
+ try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
+ writeCopierClass(out, packageName, copierClassName, validMethods, enclosingClass);
+ }
+ }
+
+ private void writeCopierClass(PrintWriter out, String packageName, String className,
+ List methods, TypeElement enclosingClass) {
+
+ String enclosingClassQualifiedName = enclosingClass.getQualifiedName().toString();
+
+ // 包声明
+ out.println("package " + packageName + ";");
+ out.println();
+
+ // 收集所有需要导入的类型
+ Set imports = collectImports(methods);
+ for (String importLine : imports) {
+ out.println("import " + importLine + ";");
+ }
+ out.println();
+
+ // 类注释
+ out.println("/**");
+ out.println(" * 自动生成的拷贝类");
+ out.println(" * 包含 " + methods.size() + " 个拷贝方法");
+ out.println(" * 由 {@link " + enclosingClassQualifiedName + "} 中的方法生成");
+ out.println(" */");
+
+ // 类声明
+ out.println("public class " + className + " {");
+ out.println();
+
+ // 为每个方法生成拷贝方法
+ for (ExecutableElement method : methods) {
+ writeCopierMethod(out, method, enclosingClass);
+ out.println();
+ }
+
+ out.println("}");
+ }
+
+ private Set collectImports(List methods) {
+ Set imports = new java.util.HashSet<>();
+ for (ExecutableElement method : methods) {
+ List extends VariableElement> parameters = method.getParameters();
+ if (parameters.size() >= 2) {
+ TypeMirror sourceType = parameters.get(0).asType();
+ TypeMirror targetType = parameters.get(1).asType();
+
+ if (sourceType instanceof DeclaredType) {
+ TypeElement sourceElement = (TypeElement) ((DeclaredType) sourceType).asElement();
+ imports.add(sourceElement.getQualifiedName().toString());
+ }
+
+ if (targetType instanceof DeclaredType) {
+ TypeElement targetElement = (TypeElement) ((DeclaredType) targetType).asElement();
+ imports.add(targetElement.getQualifiedName().toString());
+ }
+ }
+ }
+ return imports;
+ }
+
+ private void writeCopierMethod(PrintWriter out, ExecutableElement methodElement, TypeElement enclosingClass) {
+ VariableElement sourceParam = methodElement.getParameters().get(0);
+ VariableElement targetParam = methodElement.getParameters().get(1);
+ TypeMirror sourceType = sourceParam.asType();
+ TypeMirror targetType = targetParam.asType();
+
+ if (!(sourceType instanceof DeclaredType) || !(targetType instanceof DeclaredType)) {
+ return;
+ }
+
+ TypeElement sourceElement = (TypeElement) ((DeclaredType) sourceType).asElement();
+ TypeElement targetElement = (TypeElement) ((DeclaredType) targetType).asElement();
+
+ String sourceTypeName = sourceElement.getSimpleName().toString();
+ String targetTypeName = targetElement.getSimpleName().toString();
+ String enclosingClassQualifiedName = enclosingClass.getQualifiedName().toString();
+ String methodName = methodElement.getSimpleName().toString();
+
+ // 方法注释
+ out.println(" /**");
+ out.println(" * 执行属性拷贝");
+ out.println(" * 将 " + sourceTypeName + " 对象的属性拷贝到 " + targetTypeName + " 对象");
+ out.println(" * 由 {@link " + enclosingClassQualifiedName + "#" + methodName + "(" + sourceTypeName + ", " + targetTypeName + ")} 方法生成");
+ out.println(" * @param source 源对象");
+ out.println(" * @param target 目标对象");
+ out.println(" */");
+
+ // 方法声明
+ out.println(" public static void " + methodName + "(" + sourceTypeName + " source, " + targetTypeName + " target) {");
+ out.println(" if (source == null || target == null) {");
+ out.println(" return;");
+ out.println(" }");
+ out.println();
+
+ // 生成属性拷贝代码
+ List mappings = findPropertyMappings(sourceElement, targetElement);
+ if (mappings.isEmpty()) {
+ out.println(" // 未找到可拷贝的属性");
+ } else {
+ out.println(" // 属性拷贝");
+ for (PropertyMapping mapping : mappings) {
+ out.println(" target." + mapping.setterCall.replace("(value)", "(" + "source." + mapping.getterCall + ")" + ";"));
+ }
+ }
+ out.println(" }");
+ }
+
+ private List findPropertyMappings(TypeElement sourceElement, TypeElement targetElement) {
+ List mappings = new ArrayList<>();
+ List sourceGetters = findGetterMethods(sourceElement);
+ List targetSetters = findSetterMethods(targetElement);
+
+ for (GetterMethod getter : sourceGetters) {
+ SetterMethod setter = findMatchingSetter(targetSetters, getter.propertyName, getter.returnType);
+ if (setter != null) {
+ mappings.add(new PropertyMapping(getter.propertyName, getter.methodCall, setter.methodCall));
+ }
+ }
+
+ return mappings;
+ }
+
+ private String extractPropertyName(String methodName) {
+ if (methodName.startsWith("get") || methodName.startsWith("set")) {
+ String baseName = methodName.substring(3);
+ if (!baseName.isEmpty()) {
+ return Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1);
+ }
+ } else if (methodName.startsWith("is")) {
+ String baseName = methodName.substring(2);
+ if (!baseName.isEmpty()) {
+ return Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1);
+ }
+ }
+ return methodName;
+ }
+
+ private List findGetterMethods(TypeElement element) {
+ List getters = new ArrayList<>();
+ TypeMirror currentType = element.asType();
+
+ while (currentType.getKind() == TypeKind.DECLARED) {
+ DeclaredType declaredType = (DeclaredType) currentType;
+ TypeElement currentElement = (TypeElement) declaredType.asElement();
+
+ for (Element enclosed : currentElement.getEnclosedElements()) {
+ if (enclosed.getKind() == ElementKind.METHOD && enclosed instanceof ExecutableElement) {
+ ExecutableElement method = (ExecutableElement) enclosed;
+ String methodName = method.getSimpleName().toString();
+
+ if (isGetterMethod(method, methodName)) {
+ String propertyName = extractPropertyName(methodName);
+ String methodCall = methodName + "()";
+ getters.add(new GetterMethod(propertyName, methodCall, method.getReturnType()));
+ }
+ }
+ }
+
+ currentType = currentElement.getSuperclass();
+ if (currentType.getKind() == TypeKind.NONE) {
+ break;
+ }
+ }
+ return getters;
+ }
+
+ private boolean isGetterMethod(ExecutableElement method, String methodName) {
+ if (method.getModifiers().contains(Modifier.STATIC)) return false;
+ if (!method.getParameters().isEmpty()) return false;
+
+ if (methodName.startsWith("get") && methodName.length() > 3) return true;
+ return methodName.startsWith("is") && methodName.length() > 2 &&
+ method.getReturnType().getKind() == TypeKind.BOOLEAN;
+ }
+
+ private List findSetterMethods(TypeElement element) {
+ List setters = new ArrayList<>();
+ TypeMirror currentType = element.asType();
+
+ while (currentType.getKind() == TypeKind.DECLARED) {
+ DeclaredType declaredType = (DeclaredType) currentType;
+ TypeElement currentElement = (TypeElement) declaredType.asElement();
+
+ for (Element enclosed : currentElement.getEnclosedElements()) {
+ if (enclosed.getKind() == ElementKind.METHOD && enclosed instanceof ExecutableElement) {
+ ExecutableElement method = (ExecutableElement) enclosed;
+ String methodName = method.getSimpleName().toString();
+
+ if (isSetterMethod(method, methodName)) {
+ String propertyName = extractPropertyName(methodName);
+ String methodCall = methodName + "(value)";
+ setters.add(new SetterMethod(propertyName, methodCall, method.getParameters().get(0).asType()));
+ }
+ }
+ }
+
+ currentType = currentElement.getSuperclass();
+ if (currentType.getKind() == TypeKind.NONE) {
+ break;
+ }
+ }
+ return setters;
+ }
+
+ private boolean isSetterMethod(ExecutableElement method, String methodName) {
+ if (method.getModifiers().contains(Modifier.STATIC)) return false;
+ return methodName.startsWith("set") && methodName.length() > 3 &&
+ method.getParameters().size() == 1;
+ }
+
+ private SetterMethod findMatchingSetter(List setters, String propertyName, TypeMirror getterType) {
+ for (SetterMethod setter : setters) {
+ if (setter.propertyName.equals(propertyName) && isTypeCompatible(getterType, setter.paramType)) {
+ return setter;
+ }
+ }
+ return null;
+ }
+
+ private boolean isTypeCompatible(TypeMirror sourceType, TypeMirror targetType) {
+ return typeUtils.isAssignable(sourceType, targetType) ||
+ typeUtils.isAssignable(targetType, sourceType);
+ }
+
+ private boolean validateMethod(ExecutableElement method) {
+ if (method.getParameters().size() != 2) {
+ error("@ObjectCopier注解的方法必须恰好有2个参数", method, getAnnotationMirror(method));
+ return false;
+ }
+ if (!method.getReturnType().getKind().equals(TypeKind.VOID)) {
+ error("@ObjectCopier注解的方法必须返回void", method, getAnnotationMirror(method));
+ return false;
+ }
+ return true;
+ }
+
+ private String getSimpleTypeName(TypeMirror typeMirror) {
+ if (typeMirror instanceof DeclaredType) {
+ TypeElement typeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
+ return typeElement.getSimpleName().toString();
+ }
+ return typeMirror.toString();
+ }
+
+ private void error(String msg, Element element, AnnotationMirror annotationMirror) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, element, annotationMirror);
+ }
+
+ private void warn(String msg, Element element) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg, element);
+ }
+
+ private void note(String msg, Element element) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg, element);
+ }
+
+ private AnnotationMirror getAnnotationMirror(Element element) {
+ for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
+ if (mirror.getAnnotationType().toString().equals(Copier.class.getName())) {
+ return mirror;
+ }
+ }
+ return null;
+ }
+
+ // 内部类保持不变...
+ private static class PropertyMapping {
+ final String propertyName;
+ final String getterCall;
+ final String setterCall;
+
+ PropertyMapping(String propertyName, String getterCall, String setterCall) {
+ this.propertyName = propertyName;
+ this.getterCall = getterCall;
+ this.setterCall = setterCall;
+ }
+ }
+
+ private static class GetterMethod {
+ final String propertyName;
+ final String methodCall;
+ final TypeMirror returnType;
+
+ GetterMethod(String propertyName, String methodCall, TypeMirror returnType) {
+ this.propertyName = propertyName;
+ this.methodCall = methodCall;
+ this.returnType = returnType;
+ }
+ }
+
+ private static class SetterMethod {
+ final String propertyName;
+ final String methodCall;
+ final TypeMirror paramType;
+
+ SetterMethod(String propertyName, String methodCall, TypeMirror paramType) {
+ this.propertyName = propertyName;
+ this.methodCall = methodCall;
+ this.paramType = paramType;
+ }
+ }
+}
\ No newline at end of file
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/MetaObjectCopyPlugin.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/MetaObjectCopyPlugin.java
deleted file mode 100644
index 7b6d097..0000000
--- a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/MetaObjectCopyPlugin.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.acanx.util.incubator.annotation;//package com.acanx.util.object.copy;
-//
-//import com.sun.source.util.JavacTask;
-//import com.sun.source.util.Plugin;
-//import com.sun.source.util.TaskEvent;
-//import com.sun.source.util.TaskListener;
-//
-//import javax.annotation.processing.SupportedAnnotationTypes;
-//import javax.annotation.processing.SupportedSourceVersion;
-//import javax.lang.model.SourceVersion;
-//import java.io.InputStream;
-//import java.nio.charset.StandardCharsets;
-//
-//import com.sun.tools.javac.api.BasicJavacTask;
-//import com.sun.tools.javac.model.JavacElements;
-//import com.sun.tools.javac.tree.JCTree;
-//import com.sun.tools.javac.tree.TreeMaker;
-//import com.sun.tools.javac.util.Context;
-//import com.sun.tools.javac.util.Names;
-//
-//
-///**
-// * MetaObjectCopyPlugin
-// *
-// * @author ACANX
-// * @since 202506
-// */
-//
-//@SupportedAnnotationTypes("MetaObjectCopy")
-//@SupportedSourceVersion(SourceVersion.RELEASE_11)
-//public class MetaObjectCopyPlugin implements Plugin {
-//
-// static {
-// System.out.println("=== 插件初始化开始 ===");
-// String serviceFile = "META-INF/services/com.sun.source.util.Plugin";
-// try (InputStream is = MetaObjectCopyPlugin.class.getClassLoader()
-// .getResourceAsStream(serviceFile)) {
-// if (is == null) {
-// System.err.println("❌ 服务文件未找到: " + serviceFile);
-// } else {
-// String content = new String(is.readAllBytes(), StandardCharsets.UTF_8);
-// System.out.println("✅ 服务文件内容: " + content);
-//
-// if (!content.contains("com.acanx.util.object.copy.MetaObjectCopyPlugin")) {
-// System.err.println("❌ 服务文件不包含本插件类名");
-// }
-// }
-// } catch (Exception e) {
-// System.err.println("❌ 读取服务文件失败: " + e.getMessage());
-// }
-// System.out.println("=== 插件初始化结束 ===");
-// }
-//
-//
-//
-// @Override
-// public String getName() {
-// return "MetaObjectCopy";
-// }
-//
-// @Override
-// public void init(JavacTask task, String... args) {
-// // JDK 版本检测
-// String javaVersion = System.getProperty("java.version");
-// Context context = ((BasicJavacTask) task).getContext();
-// JavacElements elements = JavacElements.instance(context);
-// TreeMaker maker = TreeMaker.instance(context);
-// Names names = Names.instance(context);
-//
-// task.addTaskListener(new TaskListener() {
-// @Override
-// public void started(TaskEvent e) {}
-//
-// @Override
-// public void finished(TaskEvent e) {
-// if (e.getKind() == TaskEvent.Kind.ANALYZE) {
-// // JDK 11 兼容的扫描方式
-// JCTree.JCCompilationUnit compUnit = (JCTree.JCCompilationUnit) e.getCompilationUnit();
-//
-// if (javaVersion.startsWith("1.8")) {
-// // JDK 8 兼容方式 (使用已添加的 scan(JCTree, Void) 方法)
-//// new ASTScanner(maker, elements, names).scan(compUnit, null);
-// } else {
-// // JDK 11+ 标准方式
-//// new ASTScanner(maker, elements, names).scan(compUnit);
-// }
-// }
-// }
-// });
-// }
-//
-//
-//}
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/MetaObjectCopyProcessor.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/MetaObjectCopyProcessor.java
deleted file mode 100644
index 3be80b1..0000000
--- a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/MetaObjectCopyProcessor.java
+++ /dev/null
@@ -1,334 +0,0 @@
-//package com.acanx.util.incubator.annotation;
-//
-//
-//import com.acanx.annotation.ObjectCopy;
-//import com.google.auto.service.AutoService;
-//import org.objectweb.asm.ClassReader;
-//import org.objectweb.asm.ClassVisitor;
-//import org.objectweb.asm.ClassWriter;
-//import org.objectweb.asm.Label;
-//import org.objectweb.asm.MethodVisitor;
-//import org.objectweb.asm.Opcodes;
-//import org.objectweb.asm.Type;
-//
-//import javax.annotation.processing.AbstractProcessor;
-//import javax.annotation.processing.Filer;
-//import javax.annotation.processing.Processor;
-//import javax.annotation.processing.RoundEnvironment;
-//import javax.annotation.processing.SupportedAnnotationTypes;
-//import javax.annotation.processing.SupportedSourceVersion;
-//import javax.lang.model.SourceVersion;
-//import javax.lang.model.element.Element;
-//import javax.lang.model.element.ElementKind;
-//import javax.lang.model.element.ExecutableElement;
-//import javax.lang.model.element.TypeElement;
-//import javax.lang.model.type.ArrayType;
-//import javax.lang.model.type.DeclaredType;
-//import javax.lang.model.type.TypeMirror;
-//import javax.tools.Diagnostic;
-//import javax.tools.FileObject;
-//import javax.tools.StandardLocation;
-//import java.io.IOException;
-//import java.io.InputStream;
-//import java.io.PrintWriter;
-//import java.io.StringWriter;
-//import java.net.URL;
-//import java.nio.file.Files;
-//import java.nio.file.Path;
-//import java.nio.file.Paths;
-//import java.nio.file.StandardOpenOption;
-//import java.util.Arrays;
-//import java.util.HashMap;
-//import java.util.Map;
-//import java.util.Set;
-//
-///**
-// * ObjectValueCopyProcessor
-// *
-// * @author ACANX
-// * @since 202506
-// */
-//@SupportedAnnotationTypes("com.acanx.annotation.ObjectCopy")
-//@SupportedSourceVersion(SourceVersion.RELEASE_11)
-//@AutoService(Processor.class)
-//public class MetaObjectCopyProcessor extends AbstractProcessor {
-//
-// @Override
-// public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
-// for (Element element : roundEnv.getElementsAnnotatedWith(ObjectCopy.class)) {
-// if (element.getKind() == ElementKind.METHOD) {
-// ExecutableElement method = (ExecutableElement) element;
-// processMethod(method);
-// }
-// }
-// return true;
-// }
-//
-// private void processMethod(ExecutableElement method) {
-// try {
-// // 获取类名和方法信息
-// TypeElement classElement = (TypeElement) method.getEnclosingElement();
-// String className = classElement.getQualifiedName().toString();
-// String methodName = method.getSimpleName().toString();
-//
-// // 正确获取方法参数类型
-// Type originAsmType = getAsmType(method.getParameters().get(0).asType());
-// Type targetAsmType = getAsmType(method.getParameters().get(1).asType());
-//
-// // 正确获取方法描述符
-// String methodDesc = Type.getMethodDescriptor(Type.VOID_TYPE, originAsmType, targetAsmType);
-//
-// // 获取注解配置
-// ObjectCopy annotation = method.getAnnotation(ObjectCopy.class);
-// boolean copyNulls = annotation.copyNulls();
-// String[] ignoreFields = annotation.ignoreFields();
-// ObjectCopy.FieldMapping[] fieldMappings = annotation.fieldMappings();
-//
-// // 读取原始类字节码
-// String binaryName = processingEnv.getElementUtils().getBinaryName(classElement).toString();
-// String relativePath = binaryName.replace('.', '/')+ ".class";
-// processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "RelativePath:"+relativePath);
-// processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Class:" + getClass().getName());
-//
-//
-// // 4. 使用 Filer 获取资源
-// Filer filer = processingEnv.getFiler();
-// FileObject fileObject = filer.getResource(
-// StandardLocation.CLASS_OUTPUT, "", relativePath);
-//
-// processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Path:" + fileObject.toUri().toURL());
-// InputStream input = fileObject.openInputStream();
-// if (input == null) {
-// processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Class file not found: " + binaryName);
-// return;
-// } else {
-//
-// }
-// ClassReader cr = new ClassReader(input);
-// ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
-//
-// // 创建ClassVisitor修改方法
-// cr.accept(new ClassVisitor(Opcodes.ASM7, cw) {
-// @Override
-// public MethodVisitor visitMethod(int access, String name, String desc,
-// String signature, String[] exceptions) {
-// if (name.equals(methodName) && desc.equals(methodDesc)) {
-// return new MethodVisitor(Opcodes.ASM7,
-// super.visitMethod(access, name, desc, signature, exceptions)) {
-//
-// @Override
-// public void visitCode() {
-// // 完全替换方法体
-// generateNewMethodBody(this, method, annotation);
-// super.visitMaxs(0, 0); // 自动计算max stack/locals
-// }
-//
-// @Override
-// public void visitEnd() {
-// // 不调用super,避免原始方法体被保留
-// }
-// };
-// }
-// return super.visitMethod(access, name, desc, signature, exceptions);
-// }
-// }, ClassReader.EXPAND_FRAMES);
-//
-// // 将修改后的字节码写回文件系统
-// writeModifiedClass(className, cw.toByteArray());
-//
-// } catch (Exception e) {
-// StringWriter sw = new StringWriter();
-// e.printStackTrace(new PrintWriter(sw));
-// processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
-// "Failed to process @MetaObjectCopy: " + e.getMessage() + "\n" + sw.toString());
-// }
-// }
-//
-// /**
-// * 根据完整类名获取 .class 文件路径
-// * @param className 完整类名(如 com.example.MyClass)
-// * @return .class 文件路径,如果找不到返回 null
-// */
-// public static String findClassFilePath(String className) {
-// try {
-// // 将类名转换为资源路径
-// String resourcePath = className.replace('.', '/') + ".class";
-// // 获取系统类加载器
-// ClassLoader classLoader = ClassLoader.getSystemClassLoader();
-// // 获取资源 URL
-// URL url = classLoader.getResource(resourcePath);
-// if (url != null) {
-// // 处理特殊字符和编码
-// String decodedPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8");
-// // 处理 JAR 文件路径
-// if (decodedPath.contains("!")) {
-// return decodedPath.substring(0, decodedPath.indexOf("!"));
-// }
-// return decodedPath;
-// }
-// return null;
-// } catch (Exception e) {
-// e.printStackTrace();
-// return null;
-// }
-// }
-//
-// private void generateNewMethodBody(MethodVisitor mv, ExecutableElement method, ObjectCopy annotation) {
-// // 获取方法参数类型
-// TypeMirror originType = method.getParameters().get(0).asType();
-// TypeMirror targetType = method.getParameters().get(1).asType();
-//
-// boolean copyNulls = annotation.copyNulls();
-// String[] ignoreFields = annotation.ignoreFields();
-// ObjectCopy.FieldMapping[] fieldMappings = annotation.fieldMappings();
-//
-// // === 开始生成新方法体 ===
-// Label startLabel = new Label();
-// Label endLabel = new Label();
-// Label returnLabel = new Label();
-//
-// mv.visitLabel(startLabel);
-//
-// // 空值检查:if (origin == null || target == null) return;
-// mv.visitVarInsn(Opcodes.ALOAD, 1); // 加载origin
-// mv.visitJumpInsn(Opcodes.IFNULL, returnLabel);
-// mv.visitVarInsn(Opcodes.ALOAD, 2); // 加载target
-// mv.visitJumpInsn(Opcodes.IFNULL, returnLabel);
-//
-// // 创建字段映射表
-// Map fieldMap = new HashMap<>();
-// for (ObjectCopy.FieldMapping mapping : fieldMappings) {
-// fieldMap.put(mapping.target(), mapping.source());
-// }
-//
-// // 获取目标类字段
-// TypeElement targetElement = (TypeElement) ((DeclaredType) targetType).asElement();
-// for (Element field : targetElement.getEnclosedElements()) {
-// if (field.getKind() != ElementKind.FIELD) continue;
-//
-// String targetField = field.getSimpleName().toString();
-//
-// // 检查忽略字段
-// if (Arrays.asList(ignoreFields).contains(targetField)) continue;
-//
-// // 获取源字段名
-// String sourceField = fieldMap.getOrDefault(targetField, targetField);
-//
-// // 生成字段拷贝逻辑
-// generateFieldCopy(mv, originType, targetType, sourceField, targetField,
-// field.asType(), copyNulls);
-// }
-//
-// mv.visitJumpInsn(Opcodes.GOTO, returnLabel);
-// mv.visitLabel(endLabel);
-//
-// // 异常处理块(空实现)
-// mv.visitLabel(returnLabel);
-// mv.visitInsn(Opcodes.RETURN);
-//
-// // 局部变量表(调试信息)
-// mv.visitLocalVariable("origin", Type.getDescriptor(Object.class), null, startLabel, endLabel, 1);
-// mv.visitLocalVariable("target", Type.getDescriptor(Object.class), null, startLabel, endLabel, 2);
-// mv.visitMaxs(3, 3); // 自动计算
-// }
-//
-// private void generateFieldCopy(MethodVisitor mv, TypeMirror originType, TypeMirror targetType,
-// String sourceField, String targetField, TypeMirror fieldType,
-// boolean copyNulls) {
-// String getter = "get" + capitalize(sourceField);
-// String setter = "set" + capitalize(targetField);
-//
-// // 使用新的类型转换方法
-// Type asmFieldType = getAsmType(fieldType);
-// String fieldDesc = asmFieldType.getDescriptor();
-//
-// // 获取内部类名
-// String originInternal = getAsmType(originType).getInternalName();
-// String targetInternal = getAsmType(targetType).getInternalName();
-//
-//
-// Label afterSet = new Label();
-//
-// // 加载target对象
-// mv.visitVarInsn(Opcodes.ALOAD, 2);
-//
-// // 加载origin对象
-// mv.visitVarInsn(Opcodes.ALOAD, 1);
-//
-// // 调用origin.getter()
-// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, originInternal, getter, "()" + fieldDesc, false);
-//
-// // 空值检查
-// if (!copyNulls) {
-// mv.visitInsn(Opcodes.DUP); // 复制返回值
-// mv.visitJumpInsn(Opcodes.IFNULL, afterSet); // 如果为null则跳过setter
-// }
-//
-// // 调用target.setter()
-// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, targetInternal, setter, "(" + fieldDesc + ")V", false);
-//
-// if (!copyNulls) {
-// mv.visitLabel(afterSet);
-// mv.visitInsn(Opcodes.POP); // 弹出多余的null值
-// }
-// }
-//
-// // 工具方法保持不变
-// private String capitalize(String s) {
-// return s.substring(0, 1).toUpperCase() + s.substring(1);
-// }
-//
-// private String getInternalName(TypeMirror type) {
-// return getAsmType(type).getInternalName();
-// }
-//
-// private String getTypeDescriptor(TypeMirror type) {
-// switch (type.getKind()) {
-// case BOOLEAN: return "Z";
-// case BYTE: return "B";
-// case CHAR: return "C";
-// case SHORT: return "S";
-// case INT: return "I";
-// case LONG: return "J";
-// case FLOAT: return "F";
-// case DOUBLE: return "D";
-// case VOID: return "V";
-// default: return "L" + getInternalName(type) + ";";
-// }
-// }
-//
-// private void writeModifiedClass(String className, byte[] bytecode) throws IOException {
-// String outputPath = processingEnv.getOptions().get("outputDirectory");
-// if (outputPath == null) {
-// outputPath = "out/production/classes"; // 默认输出目录
-// }
-//
-// Path classFile = Paths.get(outputPath, className + ".class");
-// Files.createDirectories(classFile.getParent());
-// Files.write(classFile, bytecode, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
-// }
-//
-//
-// private Type getAsmType(TypeMirror typeMirror) {
-// switch (typeMirror.getKind()) {
-// case BOOLEAN: return Type.BOOLEAN_TYPE;
-// case BYTE: return Type.BYTE_TYPE;
-// case CHAR: return Type.CHAR_TYPE;
-// case SHORT: return Type.SHORT_TYPE;
-// case INT: return Type.INT_TYPE;
-// case LONG: return Type.LONG_TYPE;
-// case FLOAT: return Type.FLOAT_TYPE;
-// case DOUBLE: return Type.DOUBLE_TYPE;
-// case VOID: return Type.VOID_TYPE;
-// case ARRAY:
-// ArrayType arrayType = (ArrayType) typeMirror;
-// return Type.getType("[" + getAsmType(arrayType.getComponentType()).getDescriptor());
-// case DECLARED:
-// DeclaredType declaredType = (DeclaredType) typeMirror;
-// TypeElement typeElement = (TypeElement) declaredType.asElement();
-// return Type.getObjectType(typeElement.getQualifiedName().toString().replace('.', '/'));
-// default:
-// return Type.getType(Object.class);
-// }
-// }
-//}
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/ObjectCopyProcessor.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/ObjectCopyProcessor.java
index 2b8647e..f844dbb 100644
--- a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/ObjectCopyProcessor.java
+++ b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/ObjectCopyProcessor.java
@@ -1,448 +1,448 @@
-package com.acanx.util.incubator.annotation;
-
-import com.acanx.annotation.ObjectCopy;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.Messager;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.annotation.processing.SupportedOptions;
-import javax.annotation.processing.SupportedSourceVersion;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.Elements;
-import javax.tools.Diagnostic;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.lang.model.util.Types;
-
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.JavaFile;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-
-/**
- * ObjectCopyProcessor
- *
- * @author ACANX
- * @since 202506
- */
-@SupportedAnnotationTypes("com.acanx.annotation.ObjectCopy")
-@SupportedSourceVersion(SourceVersion.RELEASE_11)
-@SupportedOptions({"incremental"}) // 支持增量编译
-public class ObjectCopyProcessor extends AbstractProcessor {
-
- public static final String SUFFIX = "Copier";
- private Messager messager;
- private Filer filer;
- private Elements elementUtils;
- private Types typeUtils;
-
- // 全局跟踪已生成的文件
- private static final Set generatedFiles = new HashSet<>();
-
- // 收集使用说明
- private static final Map> usageInstructions = new HashMap<>();
-
- // 基本类型与包装类型映射
- private static final Map primitiveToWrapper = Map.of(
- "int", "java.lang.Integer",
- "long", "java.lang.Long",
- "double", "java.lang.Double",
- "float", "java.lang.Float",
- "boolean", "java.lang.Boolean",
- "char", "java.lang.Character",
- "byte", "java.lang.Byte",
- "short", "java.lang.Short"
- );
-
- // 兼容类型映射
- private static final Map> compatibleTypes = Map.of(
- "java.lang.String", Set.of("java.lang.CharSequence"),
- "java.lang.CharSequence", Set.of("java.lang.String"),
- "java.util.Date", Set.of("java.time.Instant", "java.time.LocalDateTime", "java.time.ZonedDateTime"),
- "java.time.Instant", Set.of("java.util.Date", "java.time.LocalDateTime", "java.time.ZonedDateTime"),
- "java.time.LocalDateTime", Set.of("java.util.Date", "java.time.Instant", "java.time.ZonedDateTime"),
- "java.time.ZonedDateTime", Set.of("java.util.Date", "java.time.Instant", "java.time.LocalDateTime")
- );
-
- @Override
- public synchronized void init(ProcessingEnvironment processingEnv) {
- super.init(processingEnv);
- messager = processingEnv.getMessager();
- filer = processingEnv.getFiler();
- elementUtils = processingEnv.getElementUtils();
- typeUtils = processingEnv.getTypeUtils();
- }
-
- @Override
- public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
- try {
- if (roundEnv.processingOver()) {
- printUsageInstructions();
- return false;
- }
-
- Set extends Element> elements = roundEnv.getElementsAnnotatedWith(ObjectCopy.class);
- List methods = elements.stream()
- .filter(e -> e.getKind() == ElementKind.METHOD)
- .map(e -> (ExecutableElement) e)
- .collect(Collectors.toList());
-
- if (methods.isEmpty()) return false;
-
- Map> methodsByClass = methods.stream()
- .collect(Collectors.groupingBy(
- method -> (TypeElement) method.getEnclosingElement()
- ));
-
- for (Map.Entry> entry : methodsByClass.entrySet()) {
- TypeElement enclosingClass = entry.getKey();
- List classMethods = entry.getValue();
- String helperClassName = enclosingClass.getSimpleName().toString() + SUFFIX;
-
- createCopierClass(enclosingClass, classMethods, helperClassName);
- collectUsageInstructions(enclosingClass, classMethods, helperClassName);
- }
-
- return true;
- } catch (Exception e) {
- messager.printMessage(Diagnostic.Kind.ERROR, "处理器异常: " + e.getMessage());
- return false;
- }
- }
-
- private void createCopierClass(TypeElement enclosingClass,
- List methods,
- String helperClassName) {
- try {
- String packageName = elementUtils.getPackageOf(enclosingClass).toString();
- String fullClassName = packageName + "." + helperClassName;
-
- if (generatedFiles.contains(fullClassName)) return;
-
- TypeSpec.Builder helperClassBuilder = TypeSpec.classBuilder(helperClassName)
- .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
- .addJavadoc("Incubator-Annotation生成的对象拷贝Copier类\n\n")
- .addJavadoc("支持功能:\n")
- .addJavadoc("- 同名同类型字段自动复制\n")
- .addJavadoc("- 基本类型与包装类型兼容\n")
- .addJavadoc("- 常用类型自动转换\n")
- .addJavadoc("- 字段映射配置\n\n")
- .addJavadoc("方法列表:\n");
-
- for (ExecutableElement method : methods) {
- String methodName = method.getSimpleName().toString();
- String helperMethodName = methodName;
- ObjectCopy annotation = method.getAnnotation(ObjectCopy.class);
-
- helperClassBuilder.addJavadoc("- $L()\n", helperMethodName);
-
- MethodSpec helperMethod = generateCopyMethod(method, helperMethodName, annotation);
- if (helperMethod != null) {
- helperClassBuilder.addMethod(helperMethod);
- }
- }
-
- JavaFile javaFile = JavaFile.builder(packageName, helperClassBuilder.build())
- .indent(" ")
- .build();
-
- javaFile.writeTo(filer);
- generatedFiles.add(fullClassName);
-
- } catch (Exception e) {
- messager.printMessage(Diagnostic.Kind.ERROR, "创建Copier类失败: " + e.getMessage(), enclosingClass);
- }
- }
-
- private MethodSpec generateCopyMethod(ExecutableElement method,
- String helperMethodName,
- ObjectCopy annotation) {
- List extends VariableElement> parameters = method.getParameters();
-
- if (parameters.size() != 2) {
- messager.printMessage(Diagnostic.Kind.ERROR, "@ObjectCopy 方法必须有两个参数", method);
- return null;
- }
-
- VariableElement sourceParam = parameters.get(0);
- VariableElement targetParam = parameters.get(1);
- TypeElement sourceType = (TypeElement) typeUtils.asElement(sourceParam.asType());
- TypeElement targetType = (TypeElement) typeUtils.asElement(targetParam.asType());
-
- if (sourceType == null || targetType == null) {
- messager.printMessage(Diagnostic.Kind.ERROR, "无法解析源或目标类型", method);
- return null;
- }
-
- // 添加方法Javadoc
- CodeBlock.Builder javadocBuilder = CodeBlock.builder();
- javadocBuilder.add("Incubator-Annotation生成的拷贝方法\n用于替换 {@link $T#$L($T, $T)}\n\n",
- method.getEnclosingElement(),
- method.getSimpleName().toString(),
- sourceParam.asType(),
- targetParam.asType());
-
- javadocBuilder.add("配置信息:\n");
- javadocBuilder.add("- copyNulls: $L\n", annotation.copyNulls());
- javadocBuilder.add("- 忽略字段: $L\n", Arrays.toString(annotation.ignoreFields()));
-
- if (annotation.fieldMappings().length > 0) {
- javadocBuilder.add("- 字段映射:\n");
- for (ObjectCopy.FieldMapping mapping : annotation.fieldMappings()) {
- javadocBuilder.add(" - $L → $L\n", mapping.s(), mapping.t());
- }
- }
-
- // 添加参数文档
- javadocBuilder.add("\n@param source 源对象,包含待拷贝的数据\n");
- javadocBuilder.add("@param target 目标对象,接收拷贝后的数据\n");
-
- MethodSpec.Builder builder = MethodSpec.methodBuilder(helperMethodName)
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
- .returns(void.class)
- .addJavadoc(javadocBuilder.build())
- .addParameter(TypeName.get(sourceParam.asType()), "source")
- .addParameter(TypeName.get(targetParam.asType()), "target");
-
- addFieldCopyStatements(builder, annotation, sourceType, targetType);
- return builder.build();
- }
-
- private void addFieldCopyStatements(MethodSpec.Builder builder,
- ObjectCopy config,
- TypeElement sourceTypeElement,
- TypeElement targetTypeElement) {
-
- boolean copyNulls = config.copyNulls();
- Set ignoredFields = new HashSet<>(Arrays.asList(config.ignoreFields()));
-
- // 1. 准备字段映射
- Map fieldMappings = new HashMap<>();
- for (ObjectCopy.FieldMapping mapping : config.fieldMappings()) {
- fieldMappings.put(mapping.s(), mapping.t());
- }
-
- // 2. 收集源类字段
- Map sourceFields = new HashMap<>();
- for (Element element : sourceTypeElement.getEnclosedElements()) {
- if (element.getKind() == ElementKind.FIELD) {
- VariableElement field = (VariableElement) element;
- sourceFields.put(field.getSimpleName().toString(), field);
- }
- }
-
- // 3. 收集目标类字段
- Map targetFields = new HashMap<>();
- for (Element element : targetTypeElement.getEnclosedElements()) {
- if (element.getKind() == ElementKind.FIELD) {
- VariableElement field = (VariableElement) element;
- targetFields.put(field.getSimpleName().toString(), field);
- }
- }
-
- // 4. 使用代码块构建拷贝逻辑
- CodeBlock.Builder codeBlock = CodeBlock.builder();
- codeBlock.add("if (null != source && null != target) {\n");
-
- // 5. 处理自动映射的同名字段
- for (String sourceFieldName : sourceFields.keySet()) {
- if (ignoredFields.contains(sourceFieldName)) continue;
- if (fieldMappings.containsKey(sourceFieldName)) continue;
-
- VariableElement sourceField = sourceFields.get(sourceFieldName);
- VariableElement targetField = targetFields.get(sourceFieldName);
-
- if (targetField != null) {
- if (isTypeCompatible(sourceField.asType(), targetField.asType())) {
- String sourceGetter = getAccessorName(sourceField, true);
- String targetSetter = getAccessorName(targetField, false);
-
- if (copyNulls) {
- codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
- } else {
- codeBlock.add(" if (null != source.$L()) {\n", sourceGetter);
- codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
- codeBlock.add(" }\n");
- }
- }
- }
- }
-
- // 6. 处理显式配置的字段映射
- for (Map.Entry mapping : fieldMappings.entrySet()) {
- String sourceFieldName = mapping.getKey();
- String targetFieldName = mapping.getValue();
-
- if (ignoredFields.contains(sourceFieldName)) continue;
-
- VariableElement sourceField = sourceFields.get(sourceFieldName);
- VariableElement targetField = targetFields.get(targetFieldName);
-
- if (sourceField == null) {
- messager.printMessage(Diagnostic.Kind.WARNING, "源字段不存在: " + sourceFieldName, sourceTypeElement);
- continue;
- }
-
- if (targetField == null) {
- messager.printMessage(Diagnostic.Kind.WARNING, "目标字段不存在: " + targetFieldName, targetTypeElement);
- continue;
- }
-
- if (!isTypeCompatible(sourceField.asType(), targetField.asType())) {
- messager.printMessage(Diagnostic.Kind.WARNING, "字段类型不兼容: " + sourceFieldName + " -> " + targetFieldName, sourceTypeElement);
- continue;
- }
-
- String sourceGetter = getAccessorName(sourceField, true);
- String targetSetter = getAccessorName(targetField, false);
- if (copyNulls) {
- codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
- } else {
- codeBlock.add(" if (null != source.$L()) {\n", sourceGetter);
- codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
- codeBlock.add(" }\n");
- }
- }
- codeBlock.add("}");
- builder.addCode(codeBlock.build());
- }
-
- /**
- * 检查类型兼容性:
- * 1. 完全相同类型
- * 2. 基本类型与对应包装类型
- * 3. 兼容类型映射(如String和CharSequence)
- * 4. 子类到父类的赋值
- */
- private boolean isTypeCompatible(TypeMirror sourceType, TypeMirror targetType) {
- // 1. 类型完全相同
- if (typeUtils.isSameType(sourceType, targetType)) {
- return true;
- }
- // 2. 基本类型与包装类型的兼容
- String sourceName = sourceType.toString();
- String targetName = targetType.toString();
- // 基本类型到包装类型
- if (primitiveToWrapper.containsKey(sourceName) &&
- primitiveToWrapper.get(sourceName).equals(targetName)) {
- return true;
- }
- // 包装类型到基本类型
- if (primitiveToWrapper.containsKey(targetName) &&
- primitiveToWrapper.get(targetName).equals(sourceName)) {
- return true;
- }
- // 3. 兼容类型映射
- Set sourceCompatible = compatibleTypes.get(sourceName);
- if (sourceCompatible != null && sourceCompatible.contains(targetName)) {
- return true;
- }
- Set targetCompatible = compatibleTypes.get(targetName);
- if (targetCompatible != null && targetCompatible.contains(sourceName)) {
- return true;
- }
- // 4. 子类到父类的赋值
- if (typeUtils.isAssignable(sourceType, targetType)) {
- return true;
- }
- // 5. 数组类型兼容(长度相同的基本类型数组)
- if (sourceType.getKind() == TypeKind.ARRAY &&
- targetType.getKind() == TypeKind.ARRAY) {
- TypeMirror sourceComponent = ((ArrayType) sourceType).getComponentType();
- TypeMirror targetComponent = ((ArrayType) targetType).getComponentType();
- return isTypeCompatible(sourceComponent, targetComponent);
- }
- return false;
- }
-
- /**
- * 获取字段的访问器方法名
- * @param field 字段元素
- * @param isGetter true: getter方法, false: setter方法
- */
- private String getAccessorName(VariableElement field, boolean isGetter) {
- String fieldName = field.getSimpleName().toString();
- String prefix = isGetter ? (field.asType().getKind() == TypeKind.BOOLEAN ? "is" : "get") : "set";
- return prefix + capitalize(fieldName);
- }
-
- private String capitalize(String str) {
- return Character.toUpperCase(str.charAt(0)) + str.substring(1);
- }
-
- private void collectUsageInstructions(TypeElement enclosingClass,
- List methods,
- String helperClassName) {
- String className = enclosingClass.getQualifiedName().toString();
- List instructions = new ArrayList<>();
-
- instructions.add("自动生成的对象拷贝Copier类: " + helperClassName);
- instructions.add("支持自动映射:");
- instructions.add(" - 同名同类型字段");
- instructions.add(" - 基本类型与包装类型");
- instructions.add(" - 常用类型转换(String/CharSequence, Date/时间类等)");
- instructions.add("请在以下方法中调用对应的Helper方法:");
-
- for (ExecutableElement method : methods) {
- String methodName = method.getSimpleName().toString();
- String helperMethodName = methodName;
-
- instructions.add(String.format(" - 方法 %s::%s 替换为: %s.%s(source, target)",
- className,
- methodName,
- helperClassName,
- helperMethodName
- ));
- }
-
- usageInstructions.put(className, instructions);
- }
-
- private void printUsageInstructions() {
- if (usageInstructions.isEmpty()) return;
-
- messager.printMessage(Diagnostic.Kind.NOTE, "============================================================");
- messager.printMessage(Diagnostic.Kind.NOTE, " 增强版对象拷贝助手使用说明");
- messager.printMessage(Diagnostic.Kind.NOTE, "============================================================");
- messager.printMessage(Diagnostic.Kind.NOTE, "支持特性:");
- messager.printMessage(Diagnostic.Kind.NOTE, "1. 同名同类型字段自动复制");
- messager.printMessage(Diagnostic.Kind.NOTE, "2. 基本类型与包装类型自动兼容");
- messager.printMessage(Diagnostic.Kind.NOTE, "3. 常用类型自动转换:");
- messager.printMessage(Diagnostic.Kind.NOTE, " - String ↔ CharSequence");
- messager.printMessage(Diagnostic.Kind.NOTE, " - java.util.Date ↔ java.time.*");
- messager.printMessage(Diagnostic.Kind.NOTE, " - 子类到父类的赋值");
- messager.printMessage(Diagnostic.Kind.NOTE, "4. 显式字段映射配置");
- messager.printMessage(Diagnostic.Kind.NOTE, "5. 空值处理控制");
- messager.printMessage(Diagnostic.Kind.NOTE, "------------------------------------------------------------");
- for (Map.Entry> entry : usageInstructions.entrySet()) {
- messager.printMessage(Diagnostic.Kind.NOTE, "处理类: " + entry.getKey());
- for (String instruction : entry.getValue()) {
- messager.printMessage(Diagnostic.Kind.NOTE, instruction);
- }
- messager.printMessage(Diagnostic.Kind.NOTE, "");
- }
- messager.printMessage(Diagnostic.Kind.NOTE, "操作步骤:");
- messager.printMessage(Diagnostic.Kind.NOTE, "1. 打开被@ObjectCopy注解的方法");
- messager.printMessage(Diagnostic.Kind.NOTE, "2. 将方法体替换为对应的Helper方法调用");
- messager.printMessage(Diagnostic.Kind.NOTE, "3. 保存并重新编译");
- messager.printMessage(Diagnostic.Kind.NOTE, "============================================================");
- }
-}
+//package com.acanx.util.incubator.annotation;
+//
+//import com.acanx.annotation.ObjectCopy;
+//import javax.annotation.processing.AbstractProcessor;
+//import javax.annotation.processing.Filer;
+//import javax.annotation.processing.Messager;
+//import javax.annotation.processing.ProcessingEnvironment;
+//import javax.annotation.processing.RoundEnvironment;
+//import javax.annotation.processing.SupportedAnnotationTypes;
+//import javax.annotation.processing.SupportedOptions;
+//import javax.annotation.processing.SupportedSourceVersion;
+//import javax.lang.model.SourceVersion;
+//import javax.lang.model.element.Element;
+//import javax.lang.model.element.ElementKind;
+//import javax.lang.model.element.ExecutableElement;
+//import javax.lang.model.element.Modifier;
+//import javax.lang.model.element.TypeElement;
+//import javax.lang.model.element.VariableElement;
+//import javax.lang.model.type.ArrayType;
+//import javax.lang.model.type.TypeKind;
+//import javax.lang.model.type.TypeMirror;
+//import javax.lang.model.util.Elements;
+//import javax.tools.Diagnostic;
+//import java.util.ArrayList;
+//import java.util.Arrays;
+//import java.util.HashMap;
+//import java.util.HashSet;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Set;
+//import java.util.stream.Collectors;
+//import javax.lang.model.util.Types;
+//
+//import com.squareup.javapoet.CodeBlock;
+//import com.squareup.javapoet.JavaFile;
+//import com.squareup.javapoet.MethodSpec;
+//import com.squareup.javapoet.TypeName;
+//import com.squareup.javapoet.TypeSpec;
+//
+///**
+// * ObjectCopyProcessor
+// *
+// * @author ACANX
+// * @since 202506
+// */
+//@SupportedAnnotationTypes("com.acanx.annotation.ObjectCopy")
+//@SupportedSourceVersion(SourceVersion.RELEASE_17)
+//@SupportedOptions({"incremental"}) // 支持增量编译
+//public class ObjectCopyProcessor extends AbstractProcessor {
+//
+// public static final String SUFFIX = "Copier";
+// private Messager messager;
+// private Filer filer;
+// private Elements elementUtils;
+// private Types typeUtils;
+//
+// // 全局跟踪已生成的文件
+// private static final Set generatedFiles = new HashSet<>();
+//
+// // 收集使用说明
+// private static final Map> usageInstructions = new HashMap<>();
+//
+// // 基本类型与包装类型映射
+// private static final Map primitiveToWrapper = Map.of(
+// "int", "java.lang.Integer",
+// "long", "java.lang.Long",
+// "double", "java.lang.Double",
+// "float", "java.lang.Float",
+// "boolean", "java.lang.Boolean",
+// "char", "java.lang.Character",
+// "byte", "java.lang.Byte",
+// "short", "java.lang.Short"
+// );
+//
+// // 兼容类型映射
+// private static final Map> compatibleTypes = Map.of(
+// "java.lang.String", Set.of("java.lang.CharSequence"),
+// "java.lang.CharSequence", Set.of("java.lang.String"),
+// "java.util.Date", Set.of("java.time.Instant", "java.time.LocalDateTime", "java.time.ZonedDateTime"),
+// "java.time.Instant", Set.of("java.util.Date", "java.time.LocalDateTime", "java.time.ZonedDateTime"),
+// "java.time.LocalDateTime", Set.of("java.util.Date", "java.time.Instant", "java.time.ZonedDateTime"),
+// "java.time.ZonedDateTime", Set.of("java.util.Date", "java.time.Instant", "java.time.LocalDateTime")
+// );
+//
+// @Override
+// public synchronized void init(ProcessingEnvironment processingEnv) {
+// super.init(processingEnv);
+// messager = processingEnv.getMessager();
+// filer = processingEnv.getFiler();
+// elementUtils = processingEnv.getElementUtils();
+// typeUtils = processingEnv.getTypeUtils();
+// }
+//
+// @Override
+// public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+// try {
+// if (roundEnv.processingOver()) {
+// printUsageInstructions();
+// return false;
+// }
+//
+// Set extends Element> elements = roundEnv.getElementsAnnotatedWith(ObjectCopy.class);
+// List methods = elements.stream()
+// .filter(e -> e.getKind() == ElementKind.METHOD)
+// .map(e -> (ExecutableElement) e)
+// .collect(Collectors.toList());
+//
+// if (methods.isEmpty()) return false;
+//
+// Map> methodsByClass = methods.stream()
+// .collect(Collectors.groupingBy(
+// method -> (TypeElement) method.getEnclosingElement()
+// ));
+//
+// for (Map.Entry> entry : methodsByClass.entrySet()) {
+// TypeElement enclosingClass = entry.getKey();
+// List classMethods = entry.getValue();
+// String helperClassName = enclosingClass.getSimpleName().toString() + SUFFIX;
+//
+// createCopierClass(enclosingClass, classMethods, helperClassName);
+// collectUsageInstructions(enclosingClass, classMethods, helperClassName);
+// }
+//
+// return true;
+// } catch (Exception e) {
+// messager.printMessage(Diagnostic.Kind.ERROR, "处理器异常: " + e.getMessage());
+// return false;
+// }
+// }
+//
+// private void createCopierClass(TypeElement enclosingClass,
+// List methods,
+// String helperClassName) {
+// try {
+// String packageName = elementUtils.getPackageOf(enclosingClass).toString();
+// String fullClassName = packageName + "." + helperClassName;
+//
+// if (generatedFiles.contains(fullClassName)) return;
+//
+// TypeSpec.Builder helperClassBuilder = TypeSpec.classBuilder(helperClassName)
+// .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+// .addJavadoc("Incubator-Annotation生成的对象拷贝Copier类\n\n")
+// .addJavadoc("支持功能:\n")
+// .addJavadoc("- 同名同类型字段自动复制\n")
+// .addJavadoc("- 基本类型与包装类型兼容\n")
+// .addJavadoc("- 常用类型自动转换\n")
+// .addJavadoc("- 字段映射配置\n\n")
+// .addJavadoc("方法列表:\n");
+//
+// for (ExecutableElement method : methods) {
+// String methodName = method.getSimpleName().toString();
+// String helperMethodName = methodName;
+// ObjectCopy annotation = method.getAnnotation(ObjectCopy.class);
+//
+// helperClassBuilder.addJavadoc("- $L()\n", helperMethodName);
+//
+// MethodSpec helperMethod = generateCopyMethod(method, helperMethodName, annotation);
+// if (helperMethod != null) {
+// helperClassBuilder.addMethod(helperMethod);
+// }
+// }
+//
+// JavaFile javaFile = JavaFile.builder(packageName, helperClassBuilder.build())
+// .indent(" ")
+// .build();
+//
+// javaFile.writeTo(filer);
+// generatedFiles.add(fullClassName);
+//
+// } catch (Exception e) {
+// messager.printMessage(Diagnostic.Kind.ERROR, "创建Copier类失败: " + e.getMessage(), enclosingClass);
+// }
+// }
+//
+// private MethodSpec generateCopyMethod(ExecutableElement method,
+// String helperMethodName,
+// ObjectCopy annotation) {
+// List extends VariableElement> parameters = method.getParameters();
+//
+// if (parameters.size() != 2) {
+// messager.printMessage(Diagnostic.Kind.ERROR, "@ObjectCopy 方法必须有两个参数", method);
+// return null;
+// }
+//
+// VariableElement sourceParam = parameters.get(0);
+// VariableElement targetParam = parameters.get(1);
+// TypeElement sourceType = (TypeElement) typeUtils.asElement(sourceParam.asType());
+// TypeElement targetType = (TypeElement) typeUtils.asElement(targetParam.asType());
+//
+// if (sourceType == null || targetType == null) {
+// messager.printMessage(Diagnostic.Kind.ERROR, "无法解析源或目标类型", method);
+// return null;
+// }
+//
+// // 添加方法Javadoc
+// CodeBlock.Builder javadocBuilder = CodeBlock.builder();
+// javadocBuilder.add("Incubator-Annotation生成的拷贝方法\n用于替换 {@link $T#$L($T, $T)}\n\n",
+// method.getEnclosingElement(),
+// method.getSimpleName().toString(),
+// sourceParam.asType(),
+// targetParam.asType());
+//
+// javadocBuilder.add("配置信息:\n");
+// javadocBuilder.add("- copyNulls: $L\n", annotation.copyNulls());
+// javadocBuilder.add("- 忽略字段: $L\n", Arrays.toString(annotation.ignoreFields()));
+//
+// if (annotation.fieldMappings().length > 0) {
+// javadocBuilder.add("- 字段映射:\n");
+// for (ObjectCopy.FieldMapping mapping : annotation.fieldMappings()) {
+// javadocBuilder.add(" - $L → $L\n", mapping.s(), mapping.t());
+// }
+// }
+//
+// // 添加参数文档
+// javadocBuilder.add("\n@param source 源对象,包含待拷贝的数据\n");
+// javadocBuilder.add("@param target 目标对象,接收拷贝后的数据\n");
+//
+// MethodSpec.Builder builder = MethodSpec.methodBuilder(helperMethodName)
+// .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+// .returns(void.class)
+// .addJavadoc(javadocBuilder.build())
+// .addParameter(TypeName.get(sourceParam.asType()), "source")
+// .addParameter(TypeName.get(targetParam.asType()), "target");
+//
+// addFieldCopyStatements(builder, annotation, sourceType, targetType);
+// return builder.build();
+// }
+//
+// private void addFieldCopyStatements(MethodSpec.Builder builder,
+// ObjectCopy config,
+// TypeElement sourceTypeElement,
+// TypeElement targetTypeElement) {
+//
+// boolean copyNulls = config.copyNulls();
+// Set ignoredFields = new HashSet<>(Arrays.asList(config.ignoreFields()));
+//
+// // 1. 准备字段映射
+// Map fieldMappings = new HashMap<>();
+// for (ObjectCopy.FieldMapping mapping : config.fieldMappings()) {
+// fieldMappings.put(mapping.s(), mapping.t());
+// }
+//
+// // 2. 收集源类字段
+// Map sourceFields = new HashMap<>();
+// for (Element element : sourceTypeElement.getEnclosedElements()) {
+// if (element.getKind() == ElementKind.FIELD) {
+// VariableElement field = (VariableElement) element;
+// sourceFields.put(field.getSimpleName().toString(), field);
+// }
+// }
+//
+// // 3. 收集目标类字段
+// Map targetFields = new HashMap<>();
+// for (Element element : targetTypeElement.getEnclosedElements()) {
+// if (element.getKind() == ElementKind.FIELD) {
+// VariableElement field = (VariableElement) element;
+// targetFields.put(field.getSimpleName().toString(), field);
+// }
+// }
+//
+// // 4. 使用代码块构建拷贝逻辑
+// CodeBlock.Builder codeBlock = CodeBlock.builder();
+// codeBlock.add("if (null != source && null != target) {\n");
+//
+// // 5. 处理自动映射的同名字段
+// for (String sourceFieldName : sourceFields.keySet()) {
+// if (ignoredFields.contains(sourceFieldName)) continue;
+// if (fieldMappings.containsKey(sourceFieldName)) continue;
+//
+// VariableElement sourceField = sourceFields.get(sourceFieldName);
+// VariableElement targetField = targetFields.get(sourceFieldName);
+//
+// if (targetField != null) {
+// if (isTypeCompatible(sourceField.asType(), targetField.asType())) {
+// String sourceGetter = getAccessorName(sourceField, true);
+// String targetSetter = getAccessorName(targetField, false);
+//
+// if (copyNulls) {
+// codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
+// } else {
+// codeBlock.add(" if (null != source.$L()) {\n", sourceGetter);
+// codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
+// codeBlock.add(" }\n");
+// }
+// }
+// }
+// }
+//
+// // 6. 处理显式配置的字段映射
+// for (Map.Entry mapping : fieldMappings.entrySet()) {
+// String sourceFieldName = mapping.getKey();
+// String targetFieldName = mapping.getValue();
+//
+// if (ignoredFields.contains(sourceFieldName)) continue;
+//
+// VariableElement sourceField = sourceFields.get(sourceFieldName);
+// VariableElement targetField = targetFields.get(targetFieldName);
+//
+// if (sourceField == null) {
+// messager.printMessage(Diagnostic.Kind.WARNING, "源字段不存在: " + sourceFieldName, sourceTypeElement);
+// continue;
+// }
+//
+// if (targetField == null) {
+// messager.printMessage(Diagnostic.Kind.WARNING, "目标字段不存在: " + targetFieldName, targetTypeElement);
+// continue;
+// }
+//
+// if (!isTypeCompatible(sourceField.asType(), targetField.asType())) {
+// messager.printMessage(Diagnostic.Kind.WARNING, "字段类型不兼容: " + sourceFieldName + " -> " + targetFieldName, sourceTypeElement);
+// continue;
+// }
+//
+// String sourceGetter = getAccessorName(sourceField, true);
+// String targetSetter = getAccessorName(targetField, false);
+// if (copyNulls) {
+// codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
+// } else {
+// codeBlock.add(" if (null != source.$L()) {\n", sourceGetter);
+// codeBlock.add(" target.$L(source.$L());\n", targetSetter, sourceGetter);
+// codeBlock.add(" }\n");
+// }
+// }
+// codeBlock.add("}");
+// builder.addCode(codeBlock.build());
+// }
+//
+// /**
+// * 检查类型兼容性:
+// * 1. 完全相同类型
+// * 2. 基本类型与对应包装类型
+// * 3. 兼容类型映射(如String和CharSequence)
+// * 4. 子类到父类的赋值
+// */
+// private boolean isTypeCompatible(TypeMirror sourceType, TypeMirror targetType) {
+// // 1. 类型完全相同
+// if (typeUtils.isSameType(sourceType, targetType)) {
+// return true;
+// }
+// // 2. 基本类型与包装类型的兼容
+// String sourceName = sourceType.toString();
+// String targetName = targetType.toString();
+// // 基本类型到包装类型
+// if (primitiveToWrapper.containsKey(sourceName) &&
+// primitiveToWrapper.get(sourceName).equals(targetName)) {
+// return true;
+// }
+// // 包装类型到基本类型
+// if (primitiveToWrapper.containsKey(targetName) &&
+// primitiveToWrapper.get(targetName).equals(sourceName)) {
+// return true;
+// }
+// // 3. 兼容类型映射
+// Set sourceCompatible = compatibleTypes.get(sourceName);
+// if (sourceCompatible != null && sourceCompatible.contains(targetName)) {
+// return true;
+// }
+// Set targetCompatible = compatibleTypes.get(targetName);
+// if (targetCompatible != null && targetCompatible.contains(sourceName)) {
+// return true;
+// }
+// // 4. 子类到父类的赋值
+// if (typeUtils.isAssignable(sourceType, targetType)) {
+// return true;
+// }
+// // 5. 数组类型兼容(长度相同的基本类型数组)
+// if (sourceType.getKind() == TypeKind.ARRAY &&
+// targetType.getKind() == TypeKind.ARRAY) {
+// TypeMirror sourceComponent = ((ArrayType) sourceType).getComponentType();
+// TypeMirror targetComponent = ((ArrayType) targetType).getComponentType();
+// return isTypeCompatible(sourceComponent, targetComponent);
+// }
+// return false;
+// }
+//
+// /**
+// * 获取字段的访问器方法名
+// * @param field 字段元素
+// * @param isGetter true: getter方法, false: setter方法
+// */
+// private String getAccessorName(VariableElement field, boolean isGetter) {
+// String fieldName = field.getSimpleName().toString();
+// String prefix = isGetter ? (field.asType().getKind() == TypeKind.BOOLEAN ? "is" : "get") : "set";
+// return prefix + capitalize(fieldName);
+// }
+//
+// private String capitalize(String str) {
+// return Character.toUpperCase(str.charAt(0)) + str.substring(1);
+// }
+//
+// private void collectUsageInstructions(TypeElement enclosingClass,
+// List methods,
+// String helperClassName) {
+// String className = enclosingClass.getQualifiedName().toString();
+// List instructions = new ArrayList<>();
+//
+// instructions.add("自动生成的对象拷贝Copier类: " + helperClassName);
+// instructions.add("支持自动映射:");
+// instructions.add(" - 同名同类型字段");
+// instructions.add(" - 基本类型与包装类型");
+// instructions.add(" - 常用类型转换(String/CharSequence, Date/时间类等)");
+// instructions.add("请在以下方法中调用对应的Helper方法:");
+//
+// for (ExecutableElement method : methods) {
+// String methodName = method.getSimpleName().toString();
+// String helperMethodName = methodName;
+//
+// instructions.add(String.format(" - 方法 %s::%s 替换为: %s.%s(source, target)",
+// className,
+// methodName,
+// helperClassName,
+// helperMethodName
+// ));
+// }
+//
+// usageInstructions.put(className, instructions);
+// }
+//
+// private void printUsageInstructions() {
+// if (usageInstructions.isEmpty()) return;
+//
+// messager.printMessage(Diagnostic.Kind.NOTE, "============================================================");
+// messager.printMessage(Diagnostic.Kind.NOTE, " 增强版对象拷贝助手使用说明");
+// messager.printMessage(Diagnostic.Kind.NOTE, "============================================================");
+// messager.printMessage(Diagnostic.Kind.NOTE, "支持特性:");
+// messager.printMessage(Diagnostic.Kind.NOTE, "1. 同名同类型字段自动复制");
+// messager.printMessage(Diagnostic.Kind.NOTE, "2. 基本类型与包装类型自动兼容");
+// messager.printMessage(Diagnostic.Kind.NOTE, "3. 常用类型自动转换:");
+// messager.printMessage(Diagnostic.Kind.NOTE, " - String ↔ CharSequence");
+// messager.printMessage(Diagnostic.Kind.NOTE, " - java.util.Date ↔ java.time.*");
+// messager.printMessage(Diagnostic.Kind.NOTE, " - 子类到父类的赋值");
+// messager.printMessage(Diagnostic.Kind.NOTE, "4. 显式字段映射配置");
+// messager.printMessage(Diagnostic.Kind.NOTE, "5. 空值处理控制");
+// messager.printMessage(Diagnostic.Kind.NOTE, "------------------------------------------------------------");
+// for (Map.Entry> entry : usageInstructions.entrySet()) {
+// messager.printMessage(Diagnostic.Kind.NOTE, "处理类: " + entry.getKey());
+// for (String instruction : entry.getValue()) {
+// messager.printMessage(Diagnostic.Kind.NOTE, instruction);
+// }
+// messager.printMessage(Diagnostic.Kind.NOTE, "");
+// }
+// messager.printMessage(Diagnostic.Kind.NOTE, "操作步骤:");
+// messager.printMessage(Diagnostic.Kind.NOTE, "1. 打开被@ObjectCopy注解的方法");
+// messager.printMessage(Diagnostic.Kind.NOTE, "2. 将方法体替换为对应的Helper方法调用");
+// messager.printMessage(Diagnostic.Kind.NOTE, "3. 保存并重新编译");
+// messager.printMessage(Diagnostic.Kind.NOTE, "============================================================");
+// }
+//}
diff --git a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/PluginLoaderTest.java b/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/PluginLoaderTest.java
deleted file mode 100644
index 76f601a..0000000
--- a/autil-incubator/incubator-annotation/src/main/java/com/acanx/util/incubator/annotation/PluginLoaderTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.acanx.util.incubator.annotation;//package com.acanx.util.object.copy;
-//
-//import com.sun.source.util.Plugin;
-//
-//import java.util.ServiceLoader;
-//
-///**
-// * PluginLoaderTest
-// *
-// * @author ACANX
-// * @date 2025-06-14
-// * @since 202506
-// */
-//public class PluginLoaderTest {
-// public static void main(String[] args) {
-// System.out.println("=== 开始加载插件 ===");
-// System.out.println("类路径: " + System.getProperty("java.class.path"));
-//
-// ServiceLoader loader = ServiceLoader.load(Plugin.class);
-// int count = 0;
-//
-// for (Plugin plugin : loader) {
-// System.out.println("✅ 找到插件: " + plugin.getClass().getName());
-// System.out.println(" 插件名称: " + plugin.getName());
-// count++;
-// }
-//
-// if (count == 0) {
-// System.err.println("❌ 未找到任何插件");
-//
-// // 尝试直接加载类
-// try {
-// Class> clazz = Class.forName("com.acanx.util.object.copy.MetaObjectCopyPlugin");
-// System.out.println("ℹ️ 类存在: " + clazz);
-//
-// // 尝试实例化
-// Plugin plugin = (Plugin) clazz.getDeclaredConstructor().newInstance();
-// System.out.println("✅ 手动创建插件成功: " + plugin.getName());
-// } catch (ClassNotFoundException e) {
-// System.err.println("❌ 类未找到: com.acanx.util.object.copy.MetaObjectCopyPlugin");
-// } catch (Exception e) {
-// System.err.println("❌ 创建实例失败: " + e.getMessage());
-// }
-// }
-// }
-//}
diff --git a/autil-incubator/incubator-annotation/src/main/java/module-info.java b/autil-incubator/incubator-annotation/src/main/java/module-info.java
new file mode 100644
index 0000000..e8f79f2
--- /dev/null
+++ b/autil-incubator/incubator-annotation/src/main/java/module-info.java
@@ -0,0 +1,17 @@
+import com.acanx.util.incubator.annotation.CopierProcessor;
+
+module com.acanx.util.incubator.annotation {
+
+
+ requires java.compiler;
+ requires static jdk.compiler;
+// requires model.test;
+
+
+ // 导出注解处理器所在的包
+ exports com.acanx.util.incubator.annotation;
+ // 关键修正:打开包到jdk.compiler模块 允许反射访问
+ opens com.acanx.util.incubator.annotation to jdk.compiler;
+
+ provides javax.annotation.processing.Processor with CopierProcessor;
+}
\ No newline at end of file
diff --git a/autil-incubator/incubator-annotation/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/autil-incubator/incubator-annotation/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index affd371..bb7a6e7 100644
--- a/autil-incubator/incubator-annotation/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/autil-incubator/incubator-annotation/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -1 +1 @@
-com.acanx.util.incubator.annotation.ObjectCopyProcessor
+com.acanx.util.incubator.annotation.CopierProcessor
diff --git a/autil-incubator/incubator-annotation/src/test/java/com/acanx/meta/model/AppTest.java b/autil-incubator/incubator-annotation/src/test/java/com/acanx/meta/model/AppTest.java
index 3b4b535..5a07649 100644
--- a/autil-incubator/incubator-annotation/src/test/java/com/acanx/meta/model/AppTest.java
+++ b/autil-incubator/incubator-annotation/src/test/java/com/acanx/meta/model/AppTest.java
@@ -1,20 +1,17 @@
package com.acanx.meta.model;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
/**
* Unit test for simple App.
*/
public class AppTest {
- /**
- * Rigorous Test :-)
- */
- @Test
- public void shouldAnswerWithTrue() {
- Assertions.assertTrue(true);
- }
+// /**
+// * Rigorous Test :-)
+// */
+// @Test
+// public void shouldAnswerWithTrue() {
+// Assertions.assertTrue(true);
+// }
}
\ No newline at end of file
diff --git a/autil-incubator/incubator-annotation/src/test/java/com/acanx/meta/model/CopyTest.java b/autil-incubator/incubator-annotation/src/test/java/com/acanx/meta/model/CopyTest.java
new file mode 100644
index 0000000..04b77b0
--- /dev/null
+++ b/autil-incubator/incubator-annotation/src/test/java/com/acanx/meta/model/CopyTest.java
@@ -0,0 +1,42 @@
+//package com.acanx.meta.model;
+//
+//import com.acanx.meta.model.test.annotation.model.MessageFlex;
+//import com.acanx.meta.model.test.annotation.model.MessageStable;
+//import com.acanx.util.incubator.annotation.Copier;
+//
+///**
+// * CopyTest
+// *
+// * @author ACANX
+// * @since 20251110
+// */
+//public class CopyTest {
+//
+//
+//
+// @Copier
+// private void convert(MessageFlex flex, MessageStable stable) {};
+//
+//
+//// @ObjectCopier(ignoreNull = true, exclude = {"internalId"})
+//// private void convert1(MessageFlex flex, MessageStable stable) {
+//// // 编译后这个方法会被增强为:
+//// // if (flex == null) throw new IllegalArgumentException("Source object cannot be null");
+//// // if (stable == null) throw new IllegalArgumentException("Target object cannot be null");
+//// // stable.content = flex.content != null ? flex.content : stable.content;
+//// // stable.priority = flex.priority != null ? flex.priority : stable.priority;
+//// // stable.urgent = flex.urgent != null ? flex.urgent : stable.urgent;
+//// // stable.tags = flex.tags != null ? flex.tags : stable.tags;
+//// }
+//
+//// @ObjectCopier(strategy = ObjectCopier.CopyStrategy.DEEP)
+//// private void deepConvert(MessageFlex flex, MessageStable stable) {
+//// // 深拷贝版本的转换
+//// }
+//
+// public void processConversion(MessageFlex flex, MessageStable stable) {
+// convert(flex, stable);
+// // 其他业务逻辑
+// }
+//
+//}
diff --git a/autil-incubator/pom.xml b/autil-incubator/pom.xml
index 092ec27..1a8cc27 100644
--- a/autil-incubator/pom.xml
+++ b/autil-incubator/pom.xml
@@ -16,14 +16,13 @@
https://github.com/ACANX/AUtil
- 11
+ 21
UTF-8
- 11
3.14.1
incubator-core
-
+ incubator-annotation
diff --git a/autil-test/pom.xml b/autil-test/pom.xml
index f5e6816..f24e0dc 100644
--- a/autil-test/pom.xml
+++ b/autil-test/pom.xml
@@ -36,6 +36,25 @@
${revision}
test
+
+
+ com.acanx.util
+ incubator-annotation
+ ${revision}
+ test
+
+
+ com.acanx.meta.model
+ model-test
+ 0.5.7-SNAPSHOT
+
+
+ com.acanx.util
+ incubator-annotation
+ 0.4.3-SNAPSHOT
+ compile
+
+
@@ -47,7 +66,33 @@
${java.version}
${java.version}
+
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+ --add-exports
+ jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+
+
+ com.acanx.util.incubator.annotation.CopierProcessor
+
+ ${project.build.directory}/generated-sources/annotations
+
+
+ com.acanx.util
+ incubator-annotation
+ ${revision}
+
+
+
diff --git a/autil-test/src/main/java/com/acanx/util/enums/Copy2.java b/autil-test/src/main/java/com/acanx/util/enums/Copy2.java
new file mode 100644
index 0000000..e004f13
--- /dev/null
+++ b/autil-test/src/main/java/com/acanx/util/enums/Copy2.java
@@ -0,0 +1,27 @@
+package com.acanx.util.enums;
+
+
+import com.acanx.meta.model.test.annotation.model.MessageFlex;
+import com.acanx.meta.model.test.annotation.model.MessageStable;
+import com.acanx.util.incubator.annotation.Copier;
+
+/**
+ * CopyTest
+ *
+ * @author ACANX
+ * @since 20251110
+ */
+public class Copy2 {
+
+
+
+ @Copier
+ private void flexToStable(MessageFlex flex, MessageStable stable) {};
+
+
+ @Copier
+ private void flex2ToStable(MessageFlex flex, MessageStable stable) {};
+
+
+
+}
diff --git a/autil-test/src/test/java/com/acanx/util/annotation/CopyTest.java b/autil-test/src/test/java/com/acanx/util/annotation/CopyTest.java
new file mode 100644
index 0000000..888b2c3
--- /dev/null
+++ b/autil-test/src/test/java/com/acanx/util/annotation/CopyTest.java
@@ -0,0 +1,42 @@
+package com.acanx.util.annotation;
+
+import com.acanx.meta.model.test.annotation.model.MessageFlex;
+import com.acanx.meta.model.test.annotation.model.MessageStable;
+import com.acanx.util.incubator.annotation.Copier;
+
+/**
+ * CopyTest
+ *
+ * @author ACANX
+ * @since 20251110
+ */
+public class CopyTest {
+
+
+
+ @Copier
+ private void convert(MessageFlex flex, MessageStable stable) {};
+
+
+ @Copier(ignoreNull = true, exclude = {"internalId"})
+ private void convert1(MessageFlex flex, MessageStable stable) {
+ // 编译后这个方法会被增强为:
+ // if (flex == null) throw new IllegalArgumentException("Source object cannot be null");
+ // if (stable == null) throw new IllegalArgumentException("Target object cannot be null");
+ // stable.content = flex.content != null ? flex.content : stable.content;
+ // stable.priority = flex.priority != null ? flex.priority : stable.priority;
+ // stable.urgent = flex.urgent != null ? flex.urgent : stable.urgent;
+ // stable.tags = flex.tags != null ? flex.tags : stable.tags;
+ }
+
+ @Copier(strategy = Copier.CopyStrategy.DEEP)
+ private void deepConvert(MessageFlex flex, MessageStable stable) {
+ // 深拷贝版本的转换
+ }
+
+ public void processConversion(MessageFlex flex, MessageStable stable) {
+ convert(flex, stable);
+ // 其他业务逻辑
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 210e416..56dfcbd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,20 +72,20 @@
-
-
- sonatype-snapshots
- Sonatype Snapshot Repository
- https://central.sonatype.com/repository/maven-snapshots/
-
- false
-
-
- true
- always
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+