GraalVM Native 支持
Spring Framework 6.0 引入了将 Spring 应用程序编译为 GraalVM 原生镜像 的支持基础设施。如果您对 GraalVM 整体不熟悉,不了解它与部署在 JVM 上的应用程序有何不同,以及这对 Spring 应用程序意味着什么,请参阅专门的 Spring Boot 3.x GraalVM 原生镜像支持文档。Spring Boot 也记录了 Spring 中 GraalVM 支持的已知限制。
GraphQL Java 元数据
由于应用程序的静态分析是在构建时完成的,如果你的应用程序在运行时查找静态资源、执行反射或创建 JDK 代理,GraalVM 可能需要额外的提示。
GraphQL Java 在运行时执行三项对原生镜像敏感的任务:
-
加载用于消息国际化的资源包
-
对用于模式检查的内部类型的一些反射
-
对应用程序在模式中注册的 Java 类型进行反射。例如,当 GraphQL Java 从应用程序类型获取属性时会发生这种情况
前两项已通过Spring团队贡献给GraalVM可达性元数据仓库的可达性元数据得到处理。当构建依赖GraphQL Java的应用程序时,原生编译工具会自动获取这些元数据。但这并未涵盖列表中的第三项,因为那些类型由应用程序自身提供,必须通过其他方式发现。
原生服务器应用程序支持
在典型的 Spring for GraphQL 应用中,与 GraphQL 模式绑定的 Java 类型会作为参数或返回类型暴露在 @Controller 方法签名中。在构建的提前处理阶段,Spring for GraphQL 会使用其 o.s.g.data.method.annotation.support.SchemaMappingBeanFactoryInitializationAotProcessor 来发现相关类型,并相应地注册可达性元数据。如果你正在构建一个支持 GraalVM 的 Spring Boot 应用,这一切都会自动完成。
如果你的应用程序是"手动"注册数据获取器,某些类型可能因此无法被自动发现。此时,你应该使用 Spring Framework 的 @RegisterReflectionForBinding 来注册这些类型:
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
}
}
此应用程序声明了一个“手动”添加
DataFetcher的RuntimeWiringConfigurer通过此
DataFetcher,BookRepository将公开一个Book类型@RegisterReflectionForBinding将为Book类型以及所有作为字段公开的类型注册相关的提示
客户端支持
GraphQlClient 不一定作为 bean 存在于应用程序上下文中,并且它不会在方法签名中暴露模式中使用的 Java 类型。因此,上一节中描述的 AotProcessor 策略无法使用。对于客户端支持,Spring for GraphQL 嵌入了客户端基础设施的相关可达性元数据。对于应用程序使用的 Java 类型,应用程序应采用类似于使用 @RegisterReflectionForBinding 的“手动”数据获取器的策略:
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
}
}
在 Native 镜像中,我们需要确保在运行时可以对
Project执行反射@RegisterReflectionForBinding将为Project类型以及所有作为字段公开的类型注册相关的提示