zoukankan      html  css  js  c++  java
  • [转]java注解与APT技术

     

    下面是一个简单的自定义注解的栗子:

    package annotation;
    
    import java.lang.annotation.Documented;
    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)
    @Documented
    public @interface AnimalName {
        String value() default "";
    }

    定义了注解,并在需要的时候给相关类,类属性加上注解信息,如果没有响应的注解信息处理流程,注解可以说是没有实用价值,接下来要介绍的是java的APT(Annotation Process Tool)技术,用于处理自定义注解。

    2,APT技术

    APT(Annotation Process Tool),是一种在代码编译时处理注解,按照一定的规则,生成相应的java文件,多用于对自定义注解的处理,目前比较流行的Dagger2, ButterKnife, EventBus3都是采用APT技术,对运行时的性能影响很小。我们通过自定义注解的方式,来了解一下如何使用APT:

    1,自定义注解:

    @Target({ElementType.TYPE})   ---作用范围 Class
    
    @Retention(RetentionPolicy.CLASS)  ---生命周期:仅保留到.class文件
    
    public @interface Route {
        /** Path of route*/
        String value();  ---类似于成员变量
    }

    2,使用方式

    @Route(path = "/test/activity2")
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test2);
        }
    }

    JVM默认只会处理@override等语言自带的注解,对于自定义的注解,需要我们自己处理,java提供了一个名为AbstractProcessor.java的抽象类,我们只要继承该类,就实现自己的注解处理器,来处理自定义的@Route注解

    public class RouteProcessor extends AbstractProcessor {
    
        @Override
        public synchronized void init(ProcessingEnvironment env){ 
            // 主要做一些初始化操作
        }
    
        @Override
            public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { 
            //具体处理注解的逻辑,控制代码的生成
            processAnnotations();
        }
    
        @Override
        public Set<String> getSupportedAnnotationTypes() { 
           // 支持处理的注解类型, 在这里就是@Route
    
        }
    
        @Override
        public SourceVersion getSupportedSourceVersion() {
          //java版本 如:jdk1.6or jdk1.7
       }
    
    }

    3,自定义Processor

    @AutoService(Processor.class)
    public class HelloProcessor extends AbstractProcessor {
    
        /** 文件相关的辅助类 用于生成新的源文件、class等 */
        private Filer mFiler;
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
            super.init(processingEnv);
            mFiler = processingEnv.getFiler();
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    
            // 构建方法 此处使用到了square公司的javapoet库,用来辅助生成 类的代码
            MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("show")
                    .addModifiers(Modifier.PUBLIC);
            methodBuilder.addStatement("String test = "$N" ","hello annotation world!");
    
            /** 构建类 */
            TypeSpec finderClass = TypeSpec.classBuilder("Hello$$Inject")
                    .addModifiers(Modifier.PUBLIC)
                    .addMethod(methodBuilder.build())
                    .build();
            try {
                JavaFile.builder("com.win.test",finderClass).build().writeTo(mFiler);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return true;
        }
    
        // 支持的注解类型
        @Override
        public Set<String> getSupportedAnnotationTypes() {
            Set<String> types = new LinkedHashSet<>();
            types.add(Hello.class.getCanonicalName());
            return types;
        }
    
        @Override
        public SourceVersion getSupportedSourceVersion() {
            return super.getSupportedSourceVersion();
        }
    }

    在AS工程中使用

    @Hello("MainTest")   //自定义的Hello注解
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    }

    在项目App module的build目录下,便会生成对应的java类文件:

    这里写图片描述

    这个只是简单的栗子,我们可以在process()方法中,加入更多的业务逻辑,以实现特定功能。

  • 相关阅读:
    mac zsh
    lldb
    c++ 的整形字面值和如何确定常量类型
    Python GTK + 3教程 学习笔记 ——(7)GTK的UI设计理念
    Python GTK + 3教程 学习笔记 ——(6)gnome-tewak-tool代码学习
    c++ 一些资料
    解决github无法加载图片
    Python GTK + 3教程 学习笔记 ——(5)布局 与 glade
    wp rest api 授权方法步骤(使用JWT Authentication插件)
    解决Ionic的ion-slide-box 2条数据渲染问题
  • 原文地址:https://www.cnblogs.com/didiaoxiong/p/9114613.html
Copyright © 2011-2022 走看看