`
米奈希尔
  • 浏览: 268856 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

注解apt工具示例程序

阅读更多

  今天按照《Thinking in Java》中使用apt处理注解一节,将书中代码写了一遍,但运行过程中出现了一个问题让我很纳闷,下面先把代码呈上,问题稍后再说。

  程序功能很简单,就是从被注解的类中提取出public方法,然后使用注解处理器生成一个包含这些public方法的接口文件。

具体介绍可以参考原书。

 

ExtractInterface.java——注解定义

/**
 * 
 */
package net.lazydoggy.annotations.aptdemo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author hanzhaozhan
 *
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ExtractInterface {
	String value();
}

 

Multiplier.java——使用了注解的目标类

/**
 * 
 */
package net.lazydoggy.annotations.aptdemo;

/**
 * @author hanzhaozhan
 * 
 */
@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 static int add(int x, int y) {
		return x + y;
	}
	
	public static void main(String[] args) {
		Multiplier m = new Multiplier();
		System.out.println("11 * 16 = " + m.multiply(11, 16));
	}
}

 

InterfaceExtractorProcessor.java——注解处理器类

package net.lazydoggy.annotations.aptdemo;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.ParameterDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;

public class InterfaceExtractorProcessor implements AnnotationProcessor {
	private final AnnotationProcessorEnvironment env;
	private ArrayList<MethodDeclaration> interfaceMethods = new ArrayList<MethodDeclaration>();

	public InterfaceExtractorProcessor(AnnotationProcessorEnvironment env) {
		this.env = env;
	}

	@Override
	public void process() {
		for (TypeDeclaration typeDel : env.getSpecifiedTypeDeclarations()) {
			ExtractInterface annot = typeDel
					.getAnnotation(ExtractInterface.class);
			if (annot == null) {
				break;
			}
			for (MethodDeclaration m : typeDel.getMethods()) {
				if (m.getModifiers().toString().contains("public")
						&& !(m.getModifiers().toString().contains("static"))) {
					interfaceMethods.add(m);
				}
			}
			if (interfaceMethods.size() > 0) {
				try {
					PrintWriter writer = env.getFiler().createSourceFile(
							annot.value());
					writer.println("package "
							+ typeDel.getPackage().getQualifiedName() + ";");
					writer.println("public interface " + annot.value() + " {");
					for (MethodDeclaration m : interfaceMethods) {
						writer.print("\tpublic ");
						writer.print(m.getReturnType() + " ");
						writer.print(m.getSimpleName() + "(");
						int i = 0;
						for (ParameterDeclaration param : m.getParameters()) {
							writer.print(param.getType() + " "
									+ param.getSimpleName());
							if (++i < m.getParameters().size()) {
								writer.print(",");
							}
						}
						writer.println(");");
					}
					writer.println("}");
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
	}

}

 

InterfaceExtractorProcessorFactory.java——处理器工厂类

/**
 * 
 */
package net.lazydoggy.annotations.aptdemo;

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;

/**
 * @author hanzhaozhan
 * 
 */
public class InterfaceExtractorProcessorFactory implements
		AnnotationProcessorFactory {

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.sun.mirror.apt.AnnotationProcessorFactory#getProcessorFor(java.util
	 * .Set, com.sun.mirror.apt.AnnotationProcessorEnvironment)
	 */
	@Override
	public AnnotationProcessor getProcessorFor(
			Set<AnnotationTypeDeclaration> atds,
			AnnotationProcessorEnvironment env) {
		return new InterfaceExtractorProcessor(env);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.sun.mirror.apt.AnnotationProcessorFactory#supportedAnnotationTypes()
	 */
	@Override
	public Collection<String> supportedAnnotationTypes() {
		return Collections
				.singleton("net.lazydoggy.annotations.aptdemo.ExtractInterface");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sun.mirror.apt.AnnotationProcessorFactory#supportedOptions()
	 */
	@Override
	public Collection<String> supportedOptions() {
		return Collections.emptySet();
	}

}

 

使用下面命令:

apt -s . -nocompile -factory net.lazydoggy.annotations.aptdemo.InterfaceExtractorProcessorFactory .\net\lazydoggy\annotations\aptdemo\Multiplier.java

就会在当前执行目录下生成一个Imultiplier .java文件,里面定义了我们在处理器中写入的接口。

 

上面的程序运行时没有问题的,因为其中的一行代码被我改动过,如下:

			for (MethodDeclaration m : typeDel.getMethods()) {
				if (m.getModifiers().toString().contains("public")
						&& !(m.getModifiers().toString().contains("static"))) {
					interfaceMethods.add(m);
				}
			}

书中的代码是这样的:

			for (MethodDeclaration m : typeDel.getMethods()) {
				if (m.getModifiers().contains(Modifier.PUBLIC)
						&& !(m.getModifiers().contains(Modifier.STATIC))) {
					interfaceMethods.add(m);
				}
			}

 如果使用书中的代码是无法得到预期结果的,我使用JDK1.6,不知道JDK1.5是否可以。在JDK1.6中,getModifiers()返回Collection<Modifier>类型,而Modifier类中的静态常量(PUBLIC、STATIC等)是int类型,因此书中代码总会返回false。

上面是我的一个方法,应该有更好的方法,希望大家可以分享。

 

 

分享到:
评论
4 楼 fondOfJava 2015-05-12  
警告:不带处理器的注释类型: [ExtractInterface]
1 警告
3 楼 tianhandigeng 2013-07-05  
2楼正解
2 楼 610622106 2012-08-14  
@楼主,你弄错了

这原题使用的是:

com.sun.mirror.declaration.Modifier和javax.lang.model.element.Modifier
这两个包下的 Modifier的枚举实例都是字符串

只有java.lang.reflect.Modifier的枚举实例是int类型

而且原 think in java 上这题使用的是 com.sun.mirror.declaration.Modifier


你的代码中,已经导入了如下两个类,就没有导入 Modifier
com.sun.mirror.declaration.ParameterDeclaration; 
com.sun.mirror.declaration.TypeDeclaration;
1 楼 lg_asus 2012-08-10  
thanks very much ~

相关推荐

Global site tag (gtag.js) - Google Analytics