前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >编译时注解(一)AbstractProcessor实战

编译时注解(一)AbstractProcessor实战

作者头像
提莫队长
发布2019-02-21 15:16:18
7.1K1
发布2019-02-21 15:16:18
举报
文章被收录于专栏:刘晓杰刘晓杰

Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的。 我们并不讨论那些在运行时(Runtime)通过反射机制运行处理的注解,而是讨论在编译时(Compile time)处理的注解。下面便入手学习下Java注解处理器。

简单实践: 1.创建注解

代码语言:javascript
复制
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface MethodProcessor {
    String name() default "Method";
}

接下来就可以使用了

代码语言:javascript
复制
@MethodProcessor(name = "Method")
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

2.注解处理器 上面只是讲如何运用,其实内部是如何生成的暂时还不知道,往下看。

代码语言:javascript
复制
//@AutoService(Processor.class) 这个有木有?这是一个注解处理器,是Google开发的,
//用来生成META-INF/services/javax.annotation.processing.Processor文件的。
//引入方式     compile 'com.google.auto.service:auto-service:1.0-rc2'
@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {

    private Types mTypeUtils;
    private Elements mElementUtils;
    private Filer mFiler;
    private Messager mMessager;

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> annotations = new LinkedHashSet<>();
        //把我们自己定义的注解添加进去
        annotations.add(MethodProcessor.class.getCanonicalName());
        return annotations;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);

        mTypeUtils = processingEnv.getTypeUtils();
        mElementUtils = processingEnv.getElementUtils();
        mFiler = processingEnv.getFiler();
        mMessager = processingEnv.getMessager();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    	// // 遍历所有被注解了的元素
        for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(MethodProcessor.class)) {
            if (annotatedElement.getKind() != ElementKind.CLASS) {
                error(annotatedElement, "Only classes can be annotated with @%s", MethodProcessor.class.getSimpleName());
                return true;
            }
            // //解析,并生成代码
            analysisAnnotated(annotatedElement);
        }
        return false;
    }

    private void error(Element e, String msg, Object... args) {
        mMessager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args), e);
    }

    private static final String SUFFIX = "Test";
    private static final String packageName = "com.company.processtest";
    private static final String retStr = "";

    private void analysisAnnotated(Element classElement) {
        MethodProcessor annotation = classElement.getAnnotation(MethodProcessor.class);
        String name = annotation.name();

        String newClassName = name + SUFFIX;

        StringBuilder builder = new StringBuilder()
                .append("package " + packageName + ";\n\n")
                .append("public class ")
                .append(newClassName)
                .append(" {\n\n") // open class
                .append("\tpublic String getMessage() {\n") // open method
                .append("\t\treturn \"");

        // this is appending to the return statement
        builder.append(retStr).append(" !\\n");

        builder.append("\";\n") // end return
                .append("\t}\n") // close method
                .append("}\n"); // close class

        try { // write the file
            JavaFileObject source = mFiler.createSourceFile(packageName + "." + newClassName);
            Writer writer = source.openWriter();
            writer.write(builder.toString());
            writer.flush();
            writer.close();
        } catch (IOException e) {
        }
    }
}

最后build一下工程,生成最终的java文件 文件位置ProcessTest\app\build\generated\source\apt\debug\com\company\processtest\MethodTest.java

代码语言:javascript
复制
package com.company.processtest;

public class MethodTest {

	public String getMessage() {
		return "this is just a test !\n";
	}
}

这样,就可以使用这个类了

代码语言:javascript
复制
@MethodProcessor(name = "Method")
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MethodTest test = new MethodTest();
        test.getMessage();
    }
}

注意:注解类和AbstractProcessor必须要新建一个java库。

AbstractProcessor中生成java类,可以使用JavaPoet开源库进行编写,提升效率

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档