GraalVM 原生支援
Spring Framework 6.0 引入了將 Spring 應用程式編譯為 GraalVM Native 映象的支援基礎設施。如果您不熟悉 GraalVM,不瞭解它與在 JVM 上部署的應用程式有何不同,以及這對 Spring 應用程式意味著什麼,請參閱專門的 Spring Boot 3.x GraalVM Native Image 支援文件。Spring Boot 也記錄了 Spring 中 GraalVM 支援的已知限制。
GraphQL Java 元資料
由於 您的應用程式的靜態分析是在構建時完成的,如果您的應用程式正在查詢靜態資源、執行反射或在執行時建立 JDK 代理,GraalVM 可能需要額外的提示。
GraphQL Java 在執行時執行三項對 Native 映象敏感的任務
-
載入用於訊息國際化的資源包
-
對內部型別進行一些反射以進行模式檢查
-
對您的應用程式註冊到模式中的 Java 型別進行反射。例如,當 GraphQL Java 從應用程式型別中獲取屬性時就會發生這種情況
前兩項透過 Spring 團隊貢獻給 GraalVM 可達性元資料倉庫的可達性元資料進行處理。當構建依賴於 GraphQL Java 的應用程式時,本機編譯工具會自動獲取此元資料。這不包括我們列表中的第三項,因為這些型別是由應用程式本身提供的,必須透過其他方式發現。
Native 伺服器應用程式支援
在典型的 Spring for GraphQL 應用程式中,與 GraphQL 模式繫結的 Java 型別在 @Controller 方法簽名中作為引數或返回型別公開。在構建的 預處理階段,Spring 或 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)
}
}
| 1 | 此應用程式聲明瞭一個“手動”新增 DataFetcher 的 RuntimeWiringConfigurer |
| 2 | 透過此 DataFetcher,BookRepository 將暴露一個 Book 型別 |
| 3 | @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)
}
}
| 1 | 在 Native 映象中,我們需要確保在執行時可以對 Project 執行反射 |
| 2 | @RegisterReflectionForBinding 將為 Project 型別和所有作為欄位暴露的型別註冊相關提示 |