`
天使的左手
  • 浏览: 55596 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

apt处理自定义annotation

    博客分类:
  • java
阅读更多
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;
			}

		}
	}

}


结果

  • 大小: 36.3 KB
分享到:
评论

相关推荐

    java8源码-APTDemo:自定义AnnotationProcessor处理自己的Annotation

    @Target:用于描述注解的使用范围,如果自定义注解不存在@Target,则表示该注解可以使用在任何程序元素之上。接收参数ElementType,其值如下: /**接口、类、枚举、注解**/ ElementType.TYPE /**字段、枚举的常量**/...

    Demo利用APT处理源文件中注解信息

    本Demo着重讲解如何利用 Annotation Processing Tool(APT) 在编译期间处理源文件中的注解信息,而非在运行时通过反射来获取和处理。 APT是Java标准库的一部分,它允许开发者编写自定义的注解处理器,这些处理器在...

    重难点之JavaAnnotation手册.pdf

    在Java 6.0及更高版本中,javac编译器已经支持自定义Annotation的处理。 三、Annotation的使用和处理 - Annotation的处理通常涉及到两个主要步骤:定义和解析。定义是创建Annotation类型,解析是通过Java反射API...

    JavaAnnotation手册.pdf

    2. 自定义Annotation:自定义Annotation需要定义一个接口,这个接口就是Annotation类型。通过定义成员变量(通常带有默认值),可以为Annotation添加特定的元数据。自定义Annotation可以通过`@interface`关键字创建...

    Annotation使用手册

    Java 提供了一个名为 “apt” (Annotation Processing Tool) 的工具,用于处理 Annotation。它可以在编译阶段扫描源代码中的 Annotation,并调用预先定义好的 Annotation 处理器来完成特定的任务,例如生成额外的...

    Annotation手册

    5. **自定义Annotation**:从Java 6.0起,开发者可以创建自己的Annotation类型,定义特定的元信息。这使得开发人员能够创建特定于应用程序的Annotation,用于各种目的,如验证、持久化、事务管理等。 6. **...

    JavaAnnotation手册[借鉴].pdf

    自定义Annotation通常需要与Annotation处理器配合,如Java的Apt工具,它可以扫描源代码,根据Annotation执行相应操作,例如验证非空约束。 四、Annotation的应用场景 - **编译时检查**:如`@NonNull`可以提示...

    JDK5.0 Java Annotation 介绍(ppt)

    2. **Annotation 处理工具**:Annotation Processing Tool (apt) 是一个用于处理 Annotation 的工具,它可以分析源代码中的 Annotation,并根据这些信息生成相应的代码或文件。 三、Annotation 使用方法 1. **类型...

    基于APT的DEMO

    APT全称为Annotation Processing Tool,是Android开发中用于处理注解(Annotation)的一种工具。它允许开发者在编译期间通过自定义注解处理器来生成源代码、XML文件或其他资源,从而简化了代码编写,提高了效率。在...

    Annotation(注解)详细教程,jdk新特性

    这些标准Annotation直接被javac支持,而自定义Annotation则需要相应的处理机制来解析和利用。 Annotation的定义涉及到新的语法,它们看起来像接口,但成员变量有限制。每个Annotation成员是一个无参数的方法,代表...

    Java-Annotation手册.docx

    - `apt` 工具:在 JDK/bin 目录下,它可以扫描源代码中的 Annotation 并调用用户定义的 Annotation 处理器,执行特定任务,如验证、代码生成等。 总的来说,Java Annotation 提供了一种声明式编程的方式,使得...

    ant-apt.jar.zip

    而Ant-APT则是Ant的一个扩展库,用于支持 Annotation Processing Tool(APT),使得在Ant构建过程中能够方便地处理注解(Annotation)。本文将深入探讨Ant-APT库的原理、功能以及如何在项目中使用。 首先,Ant是...

    Annotation--学习:JDK内建Annotation

    自定义注解需要相应的处理器来处理,这通常通过Java的注解处理工具(Annotation Processing Tool, apt)或Java Compiler API实现。处理器会在编译时自动触发,解析注解并执行相应逻辑。 6. **注解的应用场景** - ...

    AOP的apt之android中的实际应用demo

    APT(Annotation Processing Tool),注解处理工具,是Java提供的一种机制,用于在编译期间处理注解。当编译器遇到特定注解时,APT会触发自定义的处理器,这些处理器可以生成额外的源代码或者编译时需要的类文件,...

    最简单的android annotation demo

    编译时处理通常通过Apt(Annotation Processing Tool)或者Android的Dagger、Butter Knife等库实现,它们在编译期间读取注解并生成相应的代码。运行时处理则需要确保注解的保留,因为Java默认情况下不会保存注解信息...

    View注入demo(模仿ButterKnife的APT方式)

    【标题】"View注入demo(模仿ButterKnife的APT方式)" 涉及的主要知识点是Android中的编程工具和注解处理技术,特别是APT(Annotation Processing Tool)和ButterKnife库的使用。APT允许开发者在编译时通过注解来生成...

    【Android APT】编译时技术 ( 开发编译时注解 )

    在Android开发中,APT(Annotation Processing Tool)是一种编译时技术,它允许开发者在源代码中使用注解(Annotations),并自动生成相应的辅助类或代码。这种技术在提高代码的可维护性和模块化方面有着显著的优势...

    Java Annotation注解.doc

    此外,还可以使用Annotation Processing Tool (APT)在编译时处理注解,生成额外的源代码或类文件。 4. **保留策略**:注解可以在编译时、运行时或两者都被保留。保留策略通过`@Retention`注解指定,例如`...

    APTStudy:APTStudy APT英文全称:Android注解处理工具是一种处理注解的工具,它对源代码文件进行检测发现其中的注解,使用注解进行额外的处理。注解在处理时可以根据源文件中的Annotation生成额外的源文件和其他文件(文件具体内容由Annotation处理器的编写者决定),APT随后编译生成源文件和原来的源文件,将它们一起生成类文件。简言之:APT可以把注解,在编译时生成代码

    APT(Android Annotation Processing Tool)是Android平台上的一个关键组件,它为开发者提供了强大的元数据处理能力。APT允许开发者定义自定义注解,并在编译时自动处理这些注解,生成额外的源代码、XML文件或者其他...

Global site tag (gtag.js) - Google Analytics