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 在執行時會執行原生映象敏感的三項任務

  1. 載入資源包用於訊息國際化

  2. 對內部型別進行一些反射用於 schema 檢查

  3. 對您的應用程式向 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 透過此 DataFetcherBookRepository 將暴露一個 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 型別和作為欄位暴露的所有型別註冊相關的提示