zoukankan      html  css  js  c++  java
  • java注解处理器之Google Auto Service

    介绍

    SPI是java提供的一种服务发现的标准,具体请看SPI介绍,但每次我们都需要自己创建services目录,以及配置文件,google的autoservice就可以帮我们省去这一步。

    使用

    maven的依赖

    <dependency>
          <groupId>com.google.auto.service</groupId>
          <artifactId>auto-service-annotations</artifactId>
          <version>1.0-rc6</version>
          <optional>true</optional>
          <scope>compile</scope>
    </dependency>
    <dependency>
          <groupId>com.google.auto.service</groupId>
          <artifactId>auto-service</artifactId>
          <version>1.0-rc6</version>
          <optional>true</optional>
          <scope>compile</scope>
    </dependency>
    

    定义接口

    public interface UserService {
    
      String userName();
    }
    

    定义接口实现,使用AutoService注解

    @AutoService(UserService.class)
    public class LocalUserService implements UserService {
    
      @Override
      public String userName() {
        return "local user";
      }
    }
    
    @AutoService(UserService.class)
    public class RemoteUserService implements UserService {
    
      @Override
      public String userName() {
        return "remote user";
      }
    }
    

    调用

    public class Client {
      public static void main(String[] args) {
        ServiceLoader<UserService> serviceLoader = ServiceLoader.load(UserService.class);
        for (UserService userService : serviceLoader) {
          System.out.println(userService.userName());
        }
      }
    }
    

    输出结果为

    local user
    remote user
    

    从编译之后的目录里可以看到已经生成了对应的配置文件

    实现

    @SupportedOptions({ "debug", "verify" })
    public class AutoServiceProcessor extends AbstractProcessor {
    	@Override
    // 处理
      public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
        try {
          return processImpl(annotations, roundEnv);
        } catch (Exception e) {
          // We don't allow exceptions of any kind to propagate to the compiler
          StringWriter writer = new StringWriter();
          e.printStackTrace(new PrintWriter(writer));
          fatalError(writer.toString());
          return true;
        }
      }
    //真正处理
    private boolean processImpl(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    //注解已经处理完毕了,创建配置文件
        if (roundEnv.processingOver()) {
          generateConfigFiles();
        } else {
    //处理注解
          processAnnotations(annotations, roundEnv);
        }
        return true;
      }
    //处理注解
    private void processAnnotations(Set<? extends TypeElement> annotations,
          RoundEnvironment roundEnv) {
    
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(AutoService.class);
        for (Element e : elements) {
          TypeElement providerImplementer = (TypeElement) e;
          AnnotationMirror annotationMirror = getAnnotationMirror(e, AutoService.class).get();
          Set<DeclaredType> providerInterfaces = getValueFieldOfClasses(annotationMirror);
          if (providerInterfaces.isEmpty()) {
            continue;
          }
          for (DeclaredType providerInterface : providerInterfaces) {
            TypeElement providerType = MoreTypes.asTypeElement(providerInterface);
            if (checkImplementer(providerImplementer, providerType)) {
              providers.put(getBinaryName(providerType), getBinaryName(providerImplementer));
            } else {
            }
          }
        }
      }
    
    //创建配置文件
      private void generateConfigFiles() {
        Filer filer = processingEnv.getFiler();
        for (String providerInterface : providers.keySet()) {
          String resourceFile = "META-INF/services/" + providerInterface;
          try {
            SortedSet<String> allServices = Sets.newTreeSet();
            try {
              FileObject existingFile = filer.getResource(StandardLocation.CLASS_OUTPUT, "",
                  resourceFile);
              Set<String> oldServices = ServicesFiles.readServiceFile(existingFile.openInputStream());
              allServices.addAll(oldServices);
            } catch (IOException e) {
            }
            Set<String> newServices = new HashSet<String>(providers.get(providerInterface));
            if (allServices.containsAll(newServices)) {
              return;
            }
            allServices.addAll(newServices);
            FileObject fileObject = filer.createResource(StandardLocation.CLASS_OUTPUT, "",
                resourceFile);
            OutputStream out = fileObject.openOutputStream();
            ServicesFiles.writeServiceFile(allServices, out);
            out.close();
          } catch (IOException e) {
            fatalError("Unable to create " + resourceFile + ", " + e);
            return;
          }
        }
      }
    
    }
    

    AutoServoce工具和Lombok工具是类似的实现原理,通过java提供的注解处理器机制,在编译期帮助我们创建一些文件或修改文件。

  • 相关阅读:
    打印二叉树中节点的所有祖先
    1.把2叉查找树转换成双向链表
    Linux下tar.xz结尾的文件的解压方法
    Floyd算法
    c缺陷与陷阱笔记-第七章 可移植性代码
    c缺陷与陷阱笔记-第六章 预处理器
    c缺陷与陷阱笔记-第四章 连接
    C语言小程序(四)、杨辉三角
    C语言小程序(三)、判断两个日期之差
    C语言小程序(二)、计算第二天日期
  • 原文地址:https://www.cnblogs.com/strongmore/p/13284444.html
Copyright © 2011-2022 走看看