GraalVM 原生支援
Spring Framework 6.0 引入了將 Spring 應用程式編譯為 GraalVM Native Image 的支援基礎架構。如果您不熟悉 GraalVM,它與部署在 JVM 上的應用程式有何不同,以及對於 Spring 應用程式的意義,請參閱專門的 Spring Boot 3.x GraalVM Native Image 支援文件。Spring Boot 也記錄了 Spring 中 GraalVM 支援的已知限制。
GraphQL Java metadata
由於 應用程式的靜態分析是在建置時完成的,如果您的應用程式在執行時尋找靜態資源、執行反射或建立 JDK 代理,GraalVM 可能需要額外的提示。
GraphQL Java 在執行時執行三項任務,這些任務對 Native Image 很敏感
-
載入訊息國際化的資源包
-
對內部類型進行一些反射以進行架構檢查
-
反射您的應用程式向架構註冊的 Java 類型。例如,當 GraphQL Java 從應用程式類型中獲取屬性時,就會發生這種情況
前兩項透過 Spring 團隊貢獻給 GraalVM reachability metadata repository 的 reachability metadata 處理。當建置依賴 GraphQL Java 的應用程式時,原生編譯工具會自動擷取此 metadata。這不包括我們列表中的第三項,因為這些類型是由應用程式本身提供的,必須透過另一種方式發現。
原生伺服器應用程式支援
在典型的 Spring for GraphQL 應用程式中,與 GraphQL 架構綁定的 Java 類型會在 @Controller
方法簽章中作為參數或回傳類型公開。在建置的 預先編譯處理階段 期間,Spring 或 GraphQL 將使用其 o.s.g.data.method.annotation.support.SchemaMappingBeanFactoryInitializationAotProcessor
來發現相關類型並相應地註冊 reachability metadata。如果您正在使用 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)
}
}
1 | 此應用程式宣告一個 RuntimeWiringConfigurer ,它「手動」新增一個 DataFetcher |
2 | 透過此 DataFetcher ,BookRepository 將公開 Book 類型 |
3 | @RegisterReflectionForBinding 將為 Book 類型和所有作為欄位公開的類型註冊相關提示 |
用戶端支援
GraphQlClient
不一定作為 bean 存在於應用程式上下文中,並且它不會在方法簽章中公開架構中使用的 Java 類型。因此,無法使用上一節中描述的 AotProcessor
策略。為了提供用戶端支援,Spring for GraphQL 嵌入了 用戶端基礎架構的相關 reachability metadata。當涉及到應用程式使用的 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)
}
}
1 | 在 Native Image 中,我們需要確保可以在執行時對 Project 執行反射 |
2 | @RegisterReflectionForBinding 將為 Project 類型和所有作為欄位公開的類型註冊相關提示 |