diff --git a/spring-core/src/main/java/org/springframework/aot/generate/DefaultGenerationContext.java b/spring-core/src/main/java/org/springframework/aot/generate/DefaultGenerationContext.java
new file mode 100644
index 0000000000..4698d28dbb
--- /dev/null
+++ b/spring-core/src/main/java/org/springframework/aot/generate/DefaultGenerationContext.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-2022 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.aot.generate;
+
+import java.io.IOException;
+
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.util.Assert;
+
+/**
+ * Default implementation of {@link GenerationContext}.
+ *
+ * @author Phillip Webb
+ * @author Stephane Nicoll
+ * @since 6.0
+ */
+public class DefaultGenerationContext implements GenerationContext {
+
+ private final ClassNameGenerator classNameGenerator;
+
+ private final GeneratedClasses generatedClasses;
+
+ private final GeneratedFiles generatedFiles;
+
+ private final RuntimeHints runtimeHints;
+
+
+ /**
+ * Create a new {@link DefaultGenerationContext} instance backed by the
+ * specified {@code generatedFiles}.
+ * @param generatedFiles the generated files
+ */
+ public DefaultGenerationContext(GeneratedFiles generatedFiles) {
+ this(new ClassNameGenerator(), generatedFiles, new RuntimeHints());
+ }
+
+ /**
+ * Create a new {@link DefaultGenerationContext} instance backed by the
+ * specified items.
+ * @param classNameGenerator the class name generator
+ * @param generatedFiles the generated files
+ * @param runtimeHints the runtime hints
+ */
+ public DefaultGenerationContext(ClassNameGenerator classNameGenerator,
+ GeneratedFiles generatedFiles, RuntimeHints runtimeHints) {
+ Assert.notNull(classNameGenerator, "'classNameGenerator' must not be null");
+ Assert.notNull(generatedFiles, "'generatedFiles' must not be null");
+ Assert.notNull(runtimeHints, "'runtimeHints' must not be null");
+ this.classNameGenerator = classNameGenerator;
+ this.generatedClasses = new GeneratedClasses(classNameGenerator);
+ this.generatedFiles = generatedFiles;
+ this.runtimeHints = runtimeHints;
+ }
+
+
+ @Override
+ public ClassNameGenerator getClassNameGenerator() {
+ return this.classNameGenerator;
+ }
+
+ @Override
+ public GeneratedClasses getClassGenerator() {
+ return this.generatedClasses;
+ }
+
+ @Override
+ public GeneratedFiles getGeneratedFiles() {
+ return this.generatedFiles;
+ }
+
+ @Override
+ public RuntimeHints getRuntimeHints() {
+ return this.runtimeHints;
+ }
+
+ /**
+ * Write any generated content out to the generated files.
+ */
+ public void writeGeneratedContent() {
+ try {
+ this.generatedClasses.writeTo(this.generatedFiles);
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+}
diff --git a/spring-core/src/main/java/org/springframework/aot/generate/GenerationContext.java b/spring-core/src/main/java/org/springframework/aot/generate/GenerationContext.java
new file mode 100644
index 0000000000..3aadb51b39
--- /dev/null
+++ b/spring-core/src/main/java/org/springframework/aot/generate/GenerationContext.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2022 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.aot.generate;
+
+import org.springframework.aot.hint.JavaSerializationHints;
+import org.springframework.aot.hint.ProxyHints;
+import org.springframework.aot.hint.ReflectionHints;
+import org.springframework.aot.hint.ResourceHints;
+import org.springframework.aot.hint.RuntimeHints;
+
+/**
+ * Central interface used for code generation.
+ *
+ * A generation context provides:
+ *
+ * - Support for {@link #getClassNameGenerator() class name generation}.
+ * - Central management of all {@link #getGeneratedFiles() generated
+ * files}.
+ * - Support for the recording of {@link #getRuntimeHints() runtime
+ * hints}.
+ *
+ *
+ * @author Phillip Webb
+ * @author Stephane Nicoll
+ * @since 6.0
+ */
+public interface GenerationContext {
+
+ /**
+ * Return the {@link ClassNameGenerator} being used by the context. Allows
+ * new class names to be generated before they are added to the
+ * {@link #getGeneratedFiles() generated files}.
+ * @return the class name generator
+ * @see #getGeneratedFiles()
+ */
+ ClassNameGenerator getClassNameGenerator();
+
+ /**
+ * Return the {@link GeneratedClasses} being used by the context. Allows a
+ * single generated class to be shared across multiple AOT processors. All
+ * generated classes are written at the end of AOT processing.
+ * @return the generated classes
+ */
+ ClassGenerator getClassGenerator();
+
+ /**
+ * Return the {@link GeneratedFiles} being used by the context. Used to
+ * write resource, java source or class bytecode files.
+ * @return the generated files
+ */
+ GeneratedFiles getGeneratedFiles();
+
+ /**
+ * Return the {@link RuntimeHints} being used by the context. Used to record
+ * {@link ReflectionHints reflection}, {@link ResourceHints resource},
+ * {@link JavaSerializationHints serialization} and {@link ProxyHints proxy}
+ * hints so that the application can run as a native image.
+ * @return the runtime hints
+ */
+ RuntimeHints getRuntimeHints();
+
+}
diff --git a/spring-core/src/test/java/org/springframework/aot/generate/DefaultGenerationContextTests.java b/spring-core/src/test/java/org/springframework/aot/generate/DefaultGenerationContextTests.java
new file mode 100644
index 0000000000..a6d84e87eb
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/aot/generate/DefaultGenerationContextTests.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2002-2022 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.aot.generate;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.aot.hint.RuntimeHints;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+
+/**
+ * Tests for {@link DefaultGenerationContext}.
+ *
+ * @author Phillip Webb
+ * @author Stephane Nicoll
+ */
+class DefaultGenerationContextTests {
+
+ private final ClassNameGenerator classNameGenerator = new ClassNameGenerator();
+
+ private final GeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
+
+ private final RuntimeHints runtimeHints = new RuntimeHints();
+
+
+ @Test
+ void createWithOnlyGeneratedFilesCreatesContext() {
+ DefaultGenerationContext context = new DefaultGenerationContext(
+ this.generatedFiles);
+ assertThat(context.getClassNameGenerator())
+ .isInstanceOf(ClassNameGenerator.class);
+ assertThat(context.getGeneratedFiles()).isSameAs(this.generatedFiles);
+ assertThat(context.getRuntimeHints()).isInstanceOf(RuntimeHints.class);
+ }
+
+ @Test
+ void createCreatesContext() {
+ DefaultGenerationContext context = new DefaultGenerationContext(
+ this.classNameGenerator, this.generatedFiles, this.runtimeHints);
+ assertThat(context.getClassNameGenerator()).isNotNull();
+ assertThat(context.getGeneratedFiles()).isNotNull();
+ assertThat(context.getRuntimeHints()).isNotNull();
+ }
+
+ @Test
+ void createWhenClassNameGeneratorIsNullThrowsException() {
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> new DefaultGenerationContext(null, this.generatedFiles,
+ this.runtimeHints))
+ .withMessage("'classNameGenerator' must not be null");
+ }
+
+ @Test
+ void createWhenGeneratedFilesIsNullThrowsException() {
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> new DefaultGenerationContext(this.classNameGenerator,
+ null, this.runtimeHints))
+ .withMessage("'generatedFiles' must not be null");
+ }
+
+ @Test
+ void createWhenRuntimeHintsIsNullThrowsException() {
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> new DefaultGenerationContext(this.classNameGenerator,
+ this.generatedFiles, null))
+ .withMessage("'runtimeHints' must not be null");
+ }
+
+ @Test
+ void getClassNameGeneratorReturnsClassNameGenerator() {
+ DefaultGenerationContext context = new DefaultGenerationContext(
+ this.classNameGenerator, this.generatedFiles, this.runtimeHints);
+ assertThat(context.getClassNameGenerator()).isSameAs(this.classNameGenerator);
+ }
+
+ @Test
+ void getGeneratedFilesReturnsGeneratedFiles() {
+ DefaultGenerationContext context = new DefaultGenerationContext(
+ this.classNameGenerator, this.generatedFiles, this.runtimeHints);
+ assertThat(context.getGeneratedFiles()).isSameAs(this.generatedFiles);
+ }
+
+ @Test
+ void getRuntimeHintsReturnsRuntimeHints() {
+ DefaultGenerationContext context = new DefaultGenerationContext(
+ this.classNameGenerator, this.generatedFiles, this.runtimeHints);
+ assertThat(context.getRuntimeHints()).isSameAs(this.runtimeHints);
+ }
+
+}