0

如果我将spring-boot-configuration-processor作为依赖项包含在内,我的构建将生成一个像这样的 json 文件:

{
  "groups": [
    {
      "name": "attachments",
      "type": "com.example.config.AttachmentsSettings",
      "sourceType": "com.example.config.AttachmentsSettings"
    }
  ],
  "properties": [
    {
      "name": "attachments.max-size",
      "type": "java.lang.Integer",
      "sourceType": "com.example.config.AttachmentsSettings",
      "defaultValue": 1024
    },
    {
      "name": "attachments.min-size",
      "type": "java.lang.Integer",
      "sourceType": "com.example.config.AttachmentsSettings"
    },
    {
      "name": "attachments.invalid-chars",
      "type": "java.lang.String",
      "sourceType": "com.example.config.AttachmentsSettings",
      "defaultValue": "abc"
    }
  ],
  "hints": []
}

我还想另外生成一个属性文件,其中列出了所有属性及其默认值,如下所示:

attachments.max-size=1024
attachments.invalid-chars=abc
# attachments.min-size=

理想情况下,我还希望它列出没有默认值但被注释掉的属性。

是否可以使用 Spring Boot 做这样的事情?还是我需要自己写一些东西?

4

1 回答 1

0

我可以像这样扩展 ConfigurationMetadataAnnotationProcessor:

@SupportedAnnotationTypes({ "*" })
public class MyConfigurationMetadataAnnotationProcessor extends ConfigurationMetadataAnnotationProcessor {

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

        Field metadataStoreField = ReflectionUtils.findField(ConfigurationMetadataAnnotationProcessor.class, "metadataStore");
        ReflectionUtils.makeAccessible(metadataStoreField);
        ReflectionUtils.setField(metadataStoreField, this, new MyMetadataStore(env));
    }

    private class MyMetadataStore extends MetadataStore {

        static final String METADATA_PROPERTIES_PATH = "META-INF/spring-configuration-metadata.properties";
        private final ProcessingEnvironment environment;

        public MyMetadataStore(ProcessingEnvironment environment) {
            super(environment);
            this.environment = environment;
        }

        @Override
        public void writeMetadata(ConfigurationMetadata metadata) throws IOException {
            if (!metadata.getItems().isEmpty()) {
                try (OutputStream outputStream = createMetadataPropertiesResource().openOutputStream()) {
                    outputStream.write(getProps(metadata).getBytes(StandardCharsets.UTF_8));
                }
            }
        }

        private String getProps(ConfigurationMetadata metadata) {
            return metadata.getItems().stream()
                    .filter(item -> item.isOfItemType(ItemMetadata.ItemType.PROPERTY))
                    .map(item -> nonNull(item.getDefaultValue()) ?
                            item.getName() + "=" + item.getDefaultValue() :
                            "# " + item.getName() + "=")
                    .collect(Collectors.joining("\n"));
        }

        private FileObject createMetadataPropertiesResource() throws IOException {
            return this.environment.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", METADATA_PROPERTIES_PATH);
        }
    }
}

然后将其作为服务添加到 META-INF 目录中:

目录结构

处理器文件只有一行: com.my.package.MyConfigurationMetadataAnnotationProcessor

我需要分两个阶段编译它 - 首先编译处理器类,然后使用它来处理注释 - 如this SO answer中所述。

于 2020-02-17T15:49:07.340 回答