Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f43e372

Browse files
committed
Polishing.
Capture class name from within the builder callback. Simplify name handling. See #3339 Original pull request: #3345
1 parent dc5483a commit f43e372

File tree

4 files changed

+57
-66
lines changed

4 files changed

+57
-66
lines changed

‎src/main/java/org/springframework/data/repository/aot/generate/AotRepositoryBuilder.java

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
import org.apache.commons.logging.Log;
3030
import org.apache.commons.logging.LogFactory;
3131
import org.jspecify.annotations.Nullable;
32+
3233
import org.springframework.aot.generate.Generated;
33-
import org.springframework.aot.generate.GeneratedTypeReference;
34-
import org.springframework.aot.hint.TypeReference;
3534
import org.springframework.data.projection.ProjectionFactory;
3635
import org.springframework.data.repository.aot.generate.AotRepositoryFragmentMetadata.ConstructorArgument;
3736
import org.springframework.data.repository.core.RepositoryInformation;
@@ -62,9 +61,9 @@ class AotRepositoryBuilder {
6261

6362
private @Nullable Consumer<AotRepositoryConstructorBuilder> constructorCustomizer;
6463
private @Nullable MethodContributorFactory methodContributorFactory;
64+
private @Nullable String targetClassName;
6565
private Consumer<AotRepositoryClassBuilder> classCustomizer;
66-
private @Nullable TypeReference targetClassName;
67-
private RepositoryConstructorBuilder constructorBuilder;
66+
private final RepositoryConstructorBuilder constructorBuilder;
6867

6968
private AotRepositoryBuilder(RepositoryInformation repositoryInformation, String moduleName,
7069
ProjectionFactory projectionFactory) {
@@ -128,15 +127,15 @@ public AotRepositoryBuilder withQueryMethodContributor(MethodContributorFactory
128127
return this;
129128
}
130129

131-
publicAotRepositoryBuilderprepare(@NullableClassNametargetClassName) {
132-
if (targetClassName == null) {
133-
withTargetClassName(null);
134-
} else {
135-
withTargetClassName(GeneratedTypeReference.of(targetClassName));
136-
}
137-
if (constructorCustomizer != null) {
138-
constructorCustomizer.accept(constructorBuilder);
139-
}
130+
/**
131+
* Configure the {@link Class#getSimpleName() simple class name} of the generated repository implementation.
132+
*
133+
* @param className the class name to use for the generated repository implementation. Defaults to the simple
134+
* {@link RepositoryInformation#getRepositoryInterface()} class name suffixed with {@code Impl}
135+
* @return {@code this}.
136+
*/
137+
publicAotRepositoryBuilderwithClassName(@NullableStringclassName) {
138+
this.targetClassName = className;
140139
return this;
141140
}
142141

@@ -184,30 +183,19 @@ public AotBundle build(TypeSpec.Builder builder) {
184183
}
185184

186185
public AotBundle build() {
187-
188-
ClassName className = ClassName
189-
.bestGuess((targetClassName != null ? targetClassName : intendedTargetClassName()).getCanonicalName());
190-
return build(TypeSpec.classBuilder(className).addAnnotation(Generated.class));
186+
return build(TypeSpec.classBuilder(getClassName()).addAnnotation(Generated.class));
191187
}
192188

193-
public TypeReferenceintendedTargetClassName() {
194-
return TypeReference.of("%s.%s".formatted(packageName(), typeName()));
189+
public ClassNamegetClassName() {
190+
return ClassName.get(packageName(), targetClassName != null ? targetClassName : typeName());
195191
}
196192

197-
public@NullableTypeReferenceactualTargetClassName() {
193+
privateMethodSpecbuildConstructor() {
198194

199-
if (targetClassName == null) {
200-
returnnull;
195+
if (constructorCustomizer != null) {
196+
constructorCustomizer.accept(constructorBuilder);
201197
}
202-
return targetClassName;
203-
}
204198

205-
AotRepositoryBuilder withTargetClassName(@Nullable TypeReference targetClassName) {
206-
this.targetClassName = targetClassName;
207-
return this;
208-
}
209-
210-
private MethodSpec buildConstructor() {
211199
return constructorBuilder.buildConstructor();
212200
}
213201

‎src/main/java/org/springframework/data/repository/aot/generate/RepositoryContributor.java

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.apache.commons.logging.Log;
2121
import org.apache.commons.logging.LogFactory;
2222
import org.jspecify.annotations.Nullable;
23+
2324
import org.springframework.aot.generate.GeneratedClass;
2425
import org.springframework.aot.generate.GeneratedTypeReference;
2526
import org.springframework.aot.generate.GenerationContext;
@@ -31,7 +32,6 @@
3132
import org.springframework.data.repository.config.AotRepositoryContext;
3233
import org.springframework.data.repository.core.RepositoryInformation;
3334
import org.springframework.data.repository.query.QueryMethod;
34-
import org.springframework.javapoet.ClassName;
3535
import org.springframework.javapoet.TypeName;
3636

3737
/**
@@ -46,8 +46,7 @@ public class RepositoryContributor {
4646
private static final Log logger = LogFactory.getLog(RepositoryContributor.class);
4747
private static final String FEATURE_NAME = "AotRepository";
4848

49-
private AotRepositoryBuilder builder;
50-
private final AotRepositoryContext repositoryContext;
49+
private final AotRepositoryBuilder builder;
5150
private @Nullable TypeReference contributedTypeName;
5251

5352
/**
@@ -57,7 +56,6 @@ public class RepositoryContributor {
5756
*/
5857
public RepositoryContributor(AotRepositoryContext repositoryContext) {
5958

60-
this.repositoryContext = repositoryContext;
6159
builder = AotRepositoryBuilder.forRepository(repositoryContext.getRepositoryInformation(),
6260
repositoryContext.getModuleName(), createProjectionFactory());
6361
}
@@ -98,39 +96,45 @@ public void contribute(GenerationContext generationContext) {
9896
.withConstructorCustomizer(this::customizeConstructor) //
9997
.withQueryMethodContributor(this::contributeQueryMethod); //
10098

99+
// TODO: temporary fix until we have a better representation of constructor arguments
100+
// decouple the description of arguments from the actual code used in the constructor initialization, super calls,
101+
// etc.
102+
RepositoryConstructorBuilder constructorBuilder = new RepositoryConstructorBuilder(builder.getGenerationMetadata());
103+
customizeConstructor(constructorBuilder);
104+
101105
GeneratedClass generatedClass = generationContext.getGeneratedClasses().getOrAddForFeatureComponent(FEATURE_NAME,
102-
ClassName.bestGuess(builder.intendedTargetClassName().getCanonicalName()), targetTypeSpec -> {
106+
builder.getClassName(), targetTypeSpec -> {
107+
108+
// capture the actual type name early on so that we can use it in the constructor.
109+
builder.withClassName(targetTypeSpec.build().name());
103110

104111
AotBundle aotBundle = builder.build(targetTypeSpec);
105-
{
106-
Class<?> repositoryInterface = getRepositoryInformation().getRepositoryInterface();
107-
String repositoryJsonFileName = getRepositoryJsonFileName(repositoryInterface);
108-
String repositoryJson;
109-
try {
110-
repositoryJson = aotBundle.metadata().toJson().toString(2);
111-
} catch (JSONException e) {
112-
throw new RuntimeException(e);
113-
}
114-
115-
if (logger.isTraceEnabled()) {
116-
logger.trace("""
117-
------ AOT Repository.json: %s ------
118-
%s
119-
-------------------
120-
""".formatted(repositoryJsonFileName, repositoryJson));
121-
122-
logger.trace("""
123-
------ AOT Generated Repository: %s ------
124-
%s
125-
-------------------
126-
""".formatted(null, aotBundle.javaFile()));
127-
}
128-
129-
generationContext.getGeneratedFiles().addResourceFile(repositoryJsonFileName, repositoryJson);
112+
Class<?> repositoryInterface = getRepositoryInformation().getRepositoryInterface();
113+
String repositoryJsonFileName = getRepositoryJsonFileName(repositoryInterface);
114+
String repositoryJson;
115+
try {
116+
repositoryJson = aotBundle.metadata().toJson().toString(2);
117+
} catch (JSONException e) {
118+
throw new RuntimeException(e);
130119
}
120+
121+
if (logger.isTraceEnabled()) {
122+
logger.trace("""
123+
------ AOT Repository.json: %s ------
124+
%s
125+
-------------------
126+
""".formatted(repositoryJsonFileName, repositoryJson));
127+
128+
logger.trace("""
129+
------ AOT Generated Repository: %s ------
130+
%s
131+
-------------------
132+
""".formatted(null, aotBundle.javaFile()));
133+
}
134+
135+
generationContext.getGeneratedFiles().addResourceFile(repositoryJsonFileName, repositoryJson);
131136
});
132137

133-
builder.prepare(generatedClass.getName()); // initialize ctor argument resolution and set type name to target
134138
this.contributedTypeName = GeneratedTypeReference.of(generatedClass.getName());
135139

136140
// generate native runtime hints - needed cause we're using the repository proxy

‎src/main/java/org/springframework/data/repository/config/AotRepositoryBeanDefinitionPropertiesDecorator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public AotRepositoryBeanDefinitionPropertiesDecorator(Supplier<CodeBlock> inheri
5252
*/
5353
public CodeBlock decorate() {
5454

55-
Assert.notNull(repositoryContributor.getContributedTypeName(), "contributed type name must not be null");
55+
Assert.notNull(repositoryContributor.getContributedTypeName(), "Contributed type name must not be null");
5656

5757
CodeBlock.Builder builder = CodeBlock.builder();
5858
// bring in properties as usual

‎src/test/java/org/springframework/data/repository/aot/generate/AotRepositoryBuilderUnitTests.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import org.springframework.data.repository.core.support.AnnotationRepositoryMetadata;
3939
import org.springframework.data.repository.core.support.RepositoryFragment;
4040
import org.springframework.data.repository.query.QueryMethod;
41-
import org.springframework.javapoet.ClassName;
4241
import org.springframework.javapoet.MethodSpec;
4342
import org.springframework.javapoet.TypeName;
4443
import org.springframework.stereotype.Repository;
@@ -82,7 +81,7 @@ void appliesCtorArguments() {
8281
ctor.addParameter("param2", String.class);
8382
ctor.addParameter("ctorScoped", TypeName.get(Object.class), false);
8483
});
85-
assertThat(repoBuilder.prepare(null).build().javaFile().toString()) //
84+
assertThat(repoBuilder.withClassName(null).build().javaFile().toString()) //
8685
.contains("private final Metric param1;") //
8786
.contains("private final String param2;") //
8887
.doesNotContain("private final Object ctorScoped;") //
@@ -102,7 +101,7 @@ void appliesCtorCodeBlock() {
102101
code.addStatement("throw new $T($S)", IllegalStateException.class, "initialization error");
103102
});
104103
});
105-
repoBuilder.prepare(null);
104+
repoBuilder.withClassName(null);
106105
assertThat(repoBuilder.build().javaFile().toString()).containsIgnoringWhitespaces(
107106
"UserRepositoryImpl() { throw new IllegalStateException(\"initialization error\"); }");
108107
}
@@ -196,7 +195,7 @@ void usesTargetTypeName() {
196195

197196
TypeReference targetType = TypeReference.of("%s__AotPostfix".formatted(UserRepository.class.getCanonicalName()));
198197

199-
assertThat(repoBuilder.prepare(ClassName.bestGuess(targetType.getCanonicalName())).build().javaFile().toString()) //
198+
assertThat(repoBuilder.withClassName(targetType.getSimpleName()).build().javaFile().toString()) //
200199
.contains("class %s".formatted(targetType.getSimpleName())) //
201200
.contains("public %s(Metric param1, String param2, Object ctorScoped)".formatted(targetType.getSimpleName()));
202201
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /