8. GraalVM Native 支持

Spring Framework 6.0 引入了将 Spring 应用程序编译为 GraalVM Native 映像的支持基础设施。 如果您不熟悉 GraalVM,不熟悉它与 JVM 上部署的应用程序有何不同,以及它对 Spring 应用程序意味着什么。 请参阅专用的 Spring Boot 3.0 GraalVM Native Image 支持文档。 Spring Boot 还记录了 Spring 中 GraalVM 支持的已知限制spring-doc.cadn.net.cn

8.1. GraphQL Java 元数据

由于应用程序的静态分析是在构建时完成的,因此 如果您的应用程序在运行时查找静态资源、执行反射或创建 JDK 代理,GraalVM 可能需要额外的提示。spring-doc.cadn.net.cn

GraphQL Java 在运行时执行本机映像可以执行的三项任务:spring-doc.cadn.net.cn

  1. 加载用于消息国际化的资源包spring-doc.cadn.net.cn

  2. 对 Schema 检查的内部类型的一些思考spring-doc.cadn.net.cn

  3. 对应用程序向架构注册的 Java 类型的反射。例如,当 GraphQL Java 从应用程序类型获取属性时,会发生这种情况spring-doc.cadn.net.cn

前两项通过 Spring 团队贡献给 GraalVM 可访问性元数据存储库的可访问性元数据进行处理。 在构建依赖于 GraphQL Java 的应用程序时,本机编译工具会自动获取此元数据。 这不包括列表中的第三项,因为这些类型由应用程序本身提供,并且必须通过另一种方式发现。spring-doc.cadn.net.cn

8.2. Native Server 应用程序支持

在典型的 Spring for GraphQL 应用程序中,与 GraphQL 模式相关的 Java 类型在@Controller方法签名 作为参数或返回类型。在构建的 Ahead Of Time (提前) 处理阶段, Spring 或 GraphQL 将使用其o.s.g.data.method.annotation.support.SchemaMappingBeanFactoryInitializationAotProcessor探索 并相应地注册可访问性元数据。 如果您正在构建支持 GraalVM 的 Spring Boot 应用程序,则这一切都会自动为您完成。spring-doc.cadn.net.cn

如果您的应用程序正在 “手动” 注册数据获取程序,则某些类型将无法被发现。 然后,您应该将它们注册到 Spring Framework 的@RegisterReflectionForBinding:spring-doc.cadn.net.cn

import graphql.schema.DataFetcher;

import org.springframework.aot.hint.annotation.RegisterReflectionForBinding;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.data.query.QuerydslDataFetcher;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;

@Configuration
@RegisterReflectionForBinding(Book.class) (3)
public class GraphQlConfiguration {

    @Bean
    RuntimeWiringConfigurer customWiringConfigurer(BookRepository bookRepository) { (1)
        DataFetcher<Book> dataFetcher = QuerydslDataFetcher.builder(bookRepository).single();
        return wiringBuilder -> wiringBuilder
                .type("Query", builder -> builder.dataFetcher("book", dataFetcher)); (2)
    }

}
1 This application declares a RuntimeWiringConfigurer that "manually" adds a DataFetcher
2 Through this DataFetcher, the BookRepository will expose a Book type
3 @RegisterReflectionForBinding will register the relevant hints for the Book type and all types exposed as fields

8.3. Client support

The GraphQlClient is not necessarily present as a bean in the application context and it does not expose the Java types used in the schema in method signatures. The AotProcessor strategy described in the section above cannot be used as a result. For client support, Spring for GraphQL embeds the relevant reachability metadata for the client infrastructure. When it comes to Java types used by the application, applications should use a similar strategy as "manual" data fetchers using @RegisterReflectionForBinding:spring-doc.cadn.net.cn

import reactor.core.publisher.Mono;

import org.springframework.aot.hint.annotation.RegisterReflectionForBinding;
import org.springframework.graphql.client.GraphQlClient;
import org.springframework.stereotype.Component;

@Component
@RegisterReflectionForBinding(Project.class) (2)
public class ProjectService {

    private final GraphQlClient graphQlClient;

    public ProjectService(GraphQlClient graphQlClient) {
        this.graphQlClient = graphQlClient;
    }

    public Mono<Project> project(String projectSlug) {
        String document = """
                query projectWithReleases($projectSlug: ID!) {
                    project(slug: $projectSlug) {
                        name
                        releases {
                            version
                        }
                    }
                }
                """;

        return this.graphQlClient.document(document)
                .variable("projectSlug", projectSlug)
                .retrieve("project")
                .toEntity(Project.class); (1)
    }
}
1 In a Native image, we need to ensure that reflection can be performed on Project at runtime
2 @RegisterReflectionForBinding will register the relevant hints for the Project type and all types exposed as fields