GraalVM 原生支援
Spring Framework 6.0 引入了用於將 Spring 應用程式編譯為 GraalVM 原生映象 的支援基礎設施。如果您對 GraalVM 總體不熟悉,或者不清楚它與部署在 JVM 上的應用程式有何不同以及對 Spring 應用程式意味著什麼,請參閱專門的 Spring Boot 3.x GraalVM 原生映象支援文件。Spring Boot 還記錄了 Spring 中 GraalVM 支援的已知限制。
GraphQL Java 元資料
由於您的應用程式的 靜態分析是在構建時完成的,如果您的應用程式在執行時查詢靜態資源、執行反射或建立 JDK 代理,GraalVM 可能需要額外的提示。
GraphQL Java 在執行時會執行原生映象敏感的三項任務
-
載入資源包用於訊息國際化
-
對內部型別進行一些反射用於 schema 檢查
-
對您的應用程式向 schema 註冊的 Java 型別進行反射。例如,當 GraphQL Java 從應用程式型別中獲取屬性時就會發生這種情況
前兩項透過可達性元資料處理,這些元資料由 Spring 團隊貢獻給了 GraalVM 可達性元資料倉庫。當構建依賴於 GraphQL Java 的應用程式時,原生編譯工具會自動獲取此元資料。這不包括列表中的第三項,因為這些型別是由應用程式本身提供的,必須透過其他方式發現。
原生伺服器應用程式支援
在典型的 Spring for GraphQL 應用程式中,與 GraphQL schema 相關的 Java 型別作為引數或返回型別暴露在 @Controller
方法簽名中。在構建的 提前處理階段 中,Spring 或 GraphQL 將使用其 o.s.g.data.method.annotation.support.SchemaMappingBeanFactoryInitializationAotProcessor
來發現相關型別並相應地註冊可達性元資料。如果您正在構建一個支援 GraalVM 的 Spring Boot 應用程式,這一切都會自動完成。
如果您的應用程式“手動”註冊 data fetcher,結果可能是一些型別不可被發現。此時您應該使用 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 存在於應用程式上下文中,並且它不會在方法簽名中暴露 schema 中使用的 Java 型別。因此,無法使用上面部分描述的 AotProcessor
策略。對於客戶端支援,Spring for GraphQL 嵌入了 客戶端基礎設施的相關可達性元資料。當涉及到應用程式使用的 Java 型別時,應用程式應採用與使用 @RegisterReflectionForBinding
的“手動”data fetcher 類似的策略
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 | 在原生映象中,我們需要確保在執行時可以對 Project 執行反射 |
2 | @RegisterReflectionForBinding 將為 Project 型別和作為欄位暴露的所有型別註冊相關的提示 |