欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
			}

		}
	}

}


结果
apt处理自定义annotation
            
    
    博客分类: java aptannotation 
  • apt处理自定义annotation
            
    
    博客分类: java aptannotation 
  • 大小: 36.3 KB
相关标签: apt annotation