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提供的注解处理器机制,在编译期帮助我们创建一些文件或修改文件。

  • 相关阅读:
    容器编排系统k8s之ReplicaSet和Deployment控制器
    容器编排系统k8s之Pod生命周期、健康/就绪状态探测以及资源限制
    容器编排系统k8s之资源标签、标签选择器、资源注解
    容器编排系统k8s之Pod资源配置清单基础
    容器编排系统k8s之Kubectl工具的基础使用
    容器编排系统k8s之基础入门
    抢先看:笔者亲历的2020年中国.NET开发者大会活动纪实
    谷歌的请求索引功能恢复了
    VuePress教程之深入理解插件API
    Linux将shell脚本配置成系统服务并设置开机自启
  • 原文地址:https://www.cnblogs.com/strongmore/p/13284444.html
Copyright © 2011-2022 走看看