apt处理自定义annotation
程序员文章站
2022-04-05 22:25:47
...
package annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ExtractInterface { String value(); }
package annotations; //包含待解析annotation的类 @ExtractInterface("IMultiplier") public class Multiplier { public int multiply(int x, int y) { int total = 0; for (int i = 0; i < x; i++) total = add(total, y); return total; } private int add(int x, int y) { return x + y; } }
package annotations; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.sun.mirror.apt.AnnotationProcessor; import com.sun.mirror.apt.AnnotationProcessorEnvironment; import com.sun.mirror.declaration.MethodDeclaration; import com.sun.mirror.declaration.Modifier; import com.sun.mirror.declaration.ParameterDeclaration; import com.sun.mirror.declaration.TypeDeclaration; //annotation处理类 public class InterfaceExtractorProcessor implements AnnotationProcessor { private final AnnotationProcessorEnvironment env; private List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>(); public InterfaceExtractorProcessor(AnnotationProcessorEnvironment env) { this.env = env; } @Override public void process() { for (TypeDeclaration type : env.getSpecifiedTypeDeclarations()) { ExtractInterface intf = type.getAnnotation(ExtractInterface.class); if (intf == null) continue; for (MethodDeclaration method : type.getMethods()) if (method.getModifiers().contains(Modifier.PUBLIC) && !method.getModifiers().contains(Modifier.STATIC)) methods.add(method); if (methods.size() > 0) { PrintWriter writer = null; try { writer = env.getFiler().createSourceFile(intf.value()); writer.println("package " + type.getPackage().getQualifiedName() + ";"); writer.println(); writer.println("public interface " + intf.value() + " {"); for (MethodDeclaration method : methods) { writer.print("\tpublic " + method.getReturnType() + " " + method.getSimpleName() + "("); Collection<ParameterDeclaration> params = method .getParameters(); int i = 0; int len = params.size(); for (ParameterDeclaration param : params) { writer.print(param.getType() + " " + param.getSimpleName()); if (++i < len) writer.print(", "); } writer.println(");"); } writer.println("}"); } catch (IOException e) { throw new RuntimeException(e); } finally { if (writer != null) { try { writer.close(); } catch (Throwable ex) { } } } } } } }
package annotations; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Set; import com.sun.mirror.apt.AnnotationProcessor; import com.sun.mirror.apt.AnnotationProcessorEnvironment; import com.sun.mirror.apt.AnnotationProcessorFactory; import com.sun.mirror.declaration.AnnotationTypeDeclaration; //每个annotation处理器类 需要有一个工厂类去创建它 public class InterfaceExtractorProcessorFactory implements AnnotationProcessorFactory { @Override public AnnotationProcessor getProcessorFor( Set<AnnotationTypeDeclaration> set, AnnotationProcessorEnvironment env) { return new InterfaceExtractorProcessor(env); } @Override public Collection<String> supportedAnnotationTypes() { return Collections.unmodifiableCollection(Arrays .asList("annotations.ExtractInterface")); } @Override public Collection<String> supportedOptions() { return Collections.emptySet(); } }
编译ExtractInterface.java
InterfaceExtractorProcessor.java
InterfaceExtractorProcessorFactory.java
最后执行
apt -factory annotations.InterfaceExtractorProcessorFactory annotations/Multiplier.java -s . //-s 表明将生成的源文件存放在哪里
--------------------------------------------------
将访问者模式应用到annotation处理上
package annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface DBTable { String value(); }
package annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Constraints { boolean primaryKey() default false; boolean allowNull() default true; boolean unique() default false; }
package annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface SQLString { int value(); String name() default ""; Constraints constraints() default @Constraints; }
package annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface SQLInteger { String name() default ""; Constraints constraints() default @Constraints; }
package annotations; @DBTable("t_member") public class Member { @SQLInteger(constraints = @Constraints(primaryKey = true)) private int id; @SQLString(value = 50, constraints = @Constraints(allowNull = false)) private String firstname; @SQLString(50) private String lastname; @SQLInteger private int age; @SQLString(name = "addr", value = 255) private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
package annotations; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Set; import com.sun.mirror.apt.AnnotationProcessor; import com.sun.mirror.apt.AnnotationProcessorEnvironment; import com.sun.mirror.apt.AnnotationProcessorFactory; import com.sun.mirror.declaration.AnnotationTypeDeclaration; import com.sun.mirror.declaration.ClassDeclaration; import com.sun.mirror.declaration.FieldDeclaration; import com.sun.mirror.declaration.TypeDeclaration; import com.sun.mirror.util.DeclarationVisitors; import com.sun.mirror.util.SimpleDeclarationVisitor; public class TableCreationProcessorFactory implements AnnotationProcessorFactory { @Override public AnnotationProcessor getProcessorFor( Set<AnnotationTypeDeclaration> set, AnnotationProcessorEnvironment env) { return new TableCreationProcessor(env); } @Override public Collection<String> supportedAnnotationTypes() { return Collections.unmodifiableCollection(Arrays.asList( "annotations.DBTable", "annotations.Constraints", "annotations.SQLString", "annotations.SQLInteger")); } @Override public Collection<String> supportedOptions() { return Collections.emptySet(); } private static class TableCreationProcessor implements AnnotationProcessor { private final AnnotationProcessorEnvironment env; private String sql = ""; private static String LINE_SEPARATOR = System .getProperty("line.separator"); public TableCreationProcessor(AnnotationProcessorEnvironment env) { this.env = env; } @Override public void process() { for (TypeDeclaration type : env.getSpecifiedTypeDeclarations()) { type.accept(DeclarationVisitors.getDeclarationScanner( new TableCreationVisitor(), DeclarationVisitors.NO_OP)); sql = sql.substring(0, sql.length() - LINE_SEPARATOR.length() - 1); sql += LINE_SEPARATOR + ")"; System.out.println("The creation sql is:\n" + sql); sql = ""; } } private class TableCreationVisitor extends SimpleDeclarationVisitor { @Override public void visitClassDeclaration(ClassDeclaration classdeclaration) { DBTable dbTable = classdeclaration.getAnnotation(DBTable.class); if (dbTable != null) { sql += "CREATE TABLE "; sql += (dbTable.value().length() < 1) ? classdeclaration .getSimpleName().toUpperCase() : dbTable.value(); sql += "(" + LINE_SEPARATOR; } } @Override public void visitFieldDeclaration(FieldDeclaration fielddeclaration) { String columnName = ""; if (fielddeclaration.getAnnotation(SQLString.class) != null) { SQLString sString = fielddeclaration .getAnnotation(SQLString.class); if (sString.name().length() < 1) columnName = fielddeclaration.getSimpleName() .toUpperCase(); else columnName = sString.name(); sql += "\t" + columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints()) + "," + LINE_SEPARATOR; } if (fielddeclaration.getAnnotation(SQLInteger.class) != null) { SQLInteger sInteger = fielddeclaration .getAnnotation(SQLInteger.class); if (sInteger.name().length() < 1) columnName = fielddeclaration.getSimpleName() .toUpperCase(); else columnName = sInteger.name(); sql += "\t" + columnName + " INT" + getConstraints(sInteger.constraints()) + "," + LINE_SEPARATOR; } } private String getConstraints(Constraints constraints) { String result = ""; if (!constraints.allowNull()) result += " NOT NULL"; if (constraints.primaryKey()) result += " PRIMARY KEY"; if (constraints.unique()) result += " UNIQUE"; return result; } } } }
结果