【问题标题】:quarkus native reflection configuration for whole package整个包的quarkus本机反射配置
【发布时间】:2022-02-15 00:04:04
【问题描述】:

我正在构建原生 quarkus 并使用 Stripe sdk 作为外部库。 为了支持 Stripe sdk,我需要创建 reflection-config.json 文件并在 application.properties quarkus.native.additional-build-args=-H:ReflectionConfigurationFiles=reflection 中设置-config.json

reflection-config.json 看起来像这样:

  {
    "name": "com.stripe.model.Customer",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.stripe.model.Customer$InvoiceSettings",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.stripe.model.StripeError",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.stripe.model.PaymentIntent",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  },
  {
    "name": "com.stripe.model.PaymentMethod",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  }....

等等。 它包含太多的类。 我的问题是是否有办法设置整个包而不是大量的类? 例如:

  {
    "name": "com.stripe.model.*",
    "allDeclaredConstructors": true,
    "allPublicConstructors": true,
    "allDeclaredMethods": true,
    "allPublicMethods": true,
    "allDeclaredFields": true,
    "allPublicFields": true
  }

没有找到任何关于它的提及。

【问题讨论】:

    标签: kotlin reflection native quarkus


    【解决方案1】:

    您可以使用 Quarkus 扩展来做到这一点,从索引中获取类并为与包匹配的所有类生成 ReflectiveClassBuildItem

    这并不难,但需要一些工作。

    您正在做的一个不太冗长的替代方法是使用@RegisterForReflection(targets = { ... })

    这是目前唯一的选择。

    【讨论】:

      【解决方案2】:

      最干净的解决方案似乎是编写 Quarkus 扩展。

      或者,如果您不想手动列出 RegisterForReflection 目标,另一种可能性是在外部生成 reflection-config.json(可能使用注释处理器?或 maven/gradle 任务)。

      【讨论】:

        【解决方案3】:

        请参阅下面的更新。

        我有完全相同的用例以编程方式添加包的所有类以进行反射,而无需编写扩展。
        我的目标是为反射添加 jOOQ 生成的 DB 类,以便我可以在带有 RESTEasy Reactive Jackson 的本机编译的 Quarkus GraalVM 映像中使用它们。
        由于这些类有很多,我真的不想在空类上手动填充 reflection-config.json 或带有 @RegisterForReflection 注释的目标。

        我将 Quarkus 2.7.0.Final (not io.quarkus.platform as it is not released yet) 与 Gradle 7.3.3 一起使用并尝试了以下方法,但不幸的是它不起作用。 但我想这仅在构建扩展时有效?

        package com.example.restapi.graal;
        
        import io.quarkus.deployment.annotations.BuildProducer;
        import io.quarkus.deployment.annotations.BuildStep;
        import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
        import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
        import org.jboss.jandex.ClassInfo;
        import org.jboss.jandex.IndexView;
        
        public class JooqReflectionProcessor {
        
            private static final String JOOQ_DB_REFLECT_CLASSES = "com\\.example\\.restapi\\.db\\..+\\.tables\\.(pojos|records)\\..+";
        
            @BuildStep
            public void build(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, CombinedIndexBuildItem indexBuildItem) {
                IndexView index = indexBuildItem.getIndex();
                for (ClassInfo clazz : index.getKnownClasses()) {
                    if (clazz.name().toString().matches(JOOQ_DB_REFLECT_CLASSES)) {
                        reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, clazz.name().toString()));
                    }
                }
            }
        
        }
        

        更新:

        它并不漂亮,但我最终编写了一个 Gradle 任务,它使用 @RegisterForReflection(targets = {...}) 注释自动创建所需的 jOOQ 反射类:

        task writeJooqReflectionClass {
            DefaultSourceDirectorySet sourceSet = project.sourceSets.findByName('main').java
        
            File jooqSrcDir = sourceSet.srcDirs
                .stream()
                .filter { it.path.replace('\\', '/').matches('.+src/generated/jooq/main') }
                .findFirst()
                .get()
        
            ArrayList<String> classesForReflection = sourceSet
                .filter {
                    it.path.contains(jooqSrcDir.path) &&
                        it.path.replace('\\', '/').matches('.+tables/(pojos|records)/.+') &&
                        it.path.endsWith('.java')
                }
                .collect { it.path.replaceAll('[\\\\|/]', '.').substring(jooqSrcDir.path.length() + 1).replace('.java', '.class') }
        
            Collections.sort(classesForReflection)
        
            File file = new File("${jooqSrcDir.path}/com/example/restapi/db", "JooqReflectionConfig.java")
            file.getParentFile().mkdirs()
            file.text = """\
            package com.example.restapi.db;
        
            import io.quarkus.runtime.annotations.RegisterForReflection;
        
            @RegisterForReflection(targets = {
                ${String.join(',\n        ', classesForReflection)}
            })
            public class JooqReflectionConfig {
        
            }
            """.stripIndent()
        }
        
        compileJava.dependsOn(writeJooqReflectionClass)
        

        例如生成带有内容的 Class com.example.restapi.db.JooqReflectionConfig

        package com.example.restapi.db;
        
        import io.quarkus.runtime.annotations.RegisterForReflection;
        
        @RegisterForReflection(targets = {
            com.example.restapi.db.master.tables.pojos.TableA.class,
            com.example.restapi.db.master.tables.pojos.TableB.class,
            com.example.restapi.db.master.tables.records.TableA.class,
            com.example.restapi.db.master.tables.records.TableB.class,
            com.example.restapi.db.mdc.tables.pojos.TableC.class,
            com.example.restapi.db.mdc.tables.pojos.TableD.class,
            com.example.restapi.db.mdc.tables.records.TableC.class,
            com.example.restapi.db.mdc.tables.records.TableD.class
        })
        public class JooqReflectionConfig {
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-26
          • 2022-01-20
          相关资源
          最近更新 更多