当前位置 博文首页 > 用心编码:Java 编程思想--注解(二)

    用心编码:Java 编程思想--注解(二)

    作者:[db:作者] 时间:2021-09-07 13:31

    1.采用 apt 工具构建注解处理器
    (1)申明注解

    /**
     *  申明注解
     *  function : 将一个类中的 public 提取出来,抽象为一个接口。
     *  value :作为抽象出来接口的名称
     *  该接口用户类级别,在编译之前对源代码进行处理。
     */
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.SOURCE)
    public @interface ExtractInterface {
    
        String value();
    
    }

    (2)使用注解

    /**
     * 使用Multiplier 注解,内部实现两个数相乘。
     */
    @ExtractInterface(value = "IMultiplier")
    public class Multiplier {
    
        public int multiplier(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;
        }
    
        public static void main(String[] args) {
            Multiplier m = new Multiplier();
            System.out.println("11 * 16 = " + m.multiplier(11, 16));
        }
    
    }

    (3)注解处理器

    /**
     * 注解处理器
     *
     * 1.首先需要加入 apt-mirror-api-0.1.jar
     * 2.需要实现 AnnotationProcessor 接口
     * 3.所有的工作都在 process() 方法中,在分析一个类的时候,我们用 MethodDeclaration 类以及其上的 getModifier() 方法找到 public 方法且不包括 static方法,
     * 找到我们所需的方法后,就将其保存在一个 集合中,然后在一个java文件中创建接口。
     */
    
    public class InterfaceExtractorProcessor implements AnnotationProcessor {
    
        private final AnnotationProcessorEnvironment env;
    
        public InterfaceExtractorProcessor(AnnotationProcessorEnvironment env) {
            this.env = env;
        }
    
        private ArrayList<MethodDeclaration> interfaceMethods = new ArrayList<MethodDeclaration>();
    
        public void process() {
            for (TypeDeclaration typeDecl : env.getSpecifiedTypeDeclarations()) {
                ExtractInterface annot = typeDecl.getAnnotation(ExtractInterface.class);
                if (annot == null) {
                    break;
                }
                for (MethodDeclaration method : typeDecl.getMethods()) {
                    if (method.getModifiers().contains(Modifier.PUBLIC) && !(method.getModifiers().contains(Modifier.STATIC))) {
                        interfaceMethods.add(method);
                    }
                }
    
                if (interfaceMethods.size() > 0) {
                    try {
                        PrintWriter writer = env.getFiler().createSourceFile(annot.value());
                        writer.println("package " + typeDecl.getPackage().getQualifiedName() + ";");
                        writer.println("public interface " + annot.value() + " {");
                        for (MethodDeclaration method : interfaceMethods) {
                            writer.print(" public ");
                            writer.print(method.getReturnType() + " ");
                            writer.print(method.getSimpleName() + " (");
                            int i = 0;
                            for (ParameterDeclaration param : method.getParameters()) {
                                writer.print(param.getType() + " " + param.getSimpleName());
                                if (++i < method.getParameters().size()) {
                                    writer.print(", ");
                                }
                                writer.print(");");
                            }
                            writer.println("}");
                            writer.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    (4)处理 “注解处理器” 的工厂

    /**
     * apt 工具需要一个工厂类来为其指明正确的处理器,然后才能调用处理器上的 process()方法。
     *
     */
    public class InterfaceExtractorProcessorFactory implements AnnotationProcessorFactory {
        public Collection<String> supportedOptions() {
            return Collections.emptySet();
        }
    
        public Collection<String> supportedAnnotationTypes() {
            return Collections.singleton("com.daxiong.annotation.base.demo03.ExtractInterface");
        }
    
        public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> set, AnnotationProcessorEnvironment annotationProcessorEnvironment) {
            return new InterfaceExtractorProcessor(annotationProcessorEnvironment);
        }
    }

    2.总结
    (1)jdk自带的注解,处理文档,覆盖等。
    (2)java 元注解,用于自定义注解之上,构建用户自己需要的注解。

    如何构建
    

    对编译后文件:java 反射机制。
    对编译前资源文件:jdk apt 构建工具。

    两种方式的区别,优缺点
    

    3.模拟 Junit 的 @Test

    cs
    下一篇:没有了