Skip to content

Commit acc670a

Browse files
committed
Reduce API surface, expose interfaces only.
1 parent db69d21 commit acc670a

File tree

7 files changed

+203
-100
lines changed

7 files changed

+203
-100
lines changed

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

+17-25
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@
2222
import java.util.LinkedHashMap;
2323
import java.util.List;
2424
import java.util.Map;
25-
import java.util.function.BiFunction;
2625
import java.util.function.Consumer;
26+
import java.util.function.Function;
2727

2828
import javax.lang.model.element.Modifier;
2929

3030
import org.apache.commons.logging.Log;
3131
import org.apache.commons.logging.LogFactory;
3232
import org.jspecify.annotations.Nullable;
33+
3334
import org.springframework.aot.generate.ClassNameGenerator;
3435
import org.springframework.aot.generate.Generated;
3536
import org.springframework.data.projection.ProjectionFactory;
@@ -43,6 +44,7 @@
4344
import org.springframework.javapoet.JavaFile;
4445
import org.springframework.javapoet.TypeName;
4546
import org.springframework.javapoet.TypeSpec;
47+
import org.springframework.util.Assert;
4648

4749
/**
4850
* Builder for AOT repository fragments.
@@ -59,8 +61,8 @@ class AotRepositoryBuilder {
5961
private final AotRepositoryFragmentMetadata generationMetadata;
6062

6163
private @Nullable Consumer<AotRepositoryConstructorBuilder> constructorCustomizer;
62-
private @Nullable BiFunction<Method, RepositoryInformation, @Nullable MethodContributor<? extends QueryMethod>> methodContributorFunction;
63-
private ClassCustomizer customizer;
64+
private @Nullable Function<Method, @Nullable MethodContributor<? extends QueryMethod>> methodContributorFunction;
65+
private Consumer<AotRepositoryClassBuilder> classCustomizer;
6466

6567
private AotRepositoryBuilder(RepositoryInformation repositoryInformation, ProjectionFactory projectionFactory) {
6668

@@ -73,7 +75,7 @@ private AotRepositoryBuilder(RepositoryInformation repositoryInformation, Projec
7375
.initializer("$T.getLog($T.class)", TypeName.get(LogFactory.class), this.generationMetadata.getTargetTypeName())
7476
.build());
7577

76-
this.customizer = (info, builder) -> {};
78+
this.classCustomizer = (builder) -> {};
7779
}
7880

7981
public static <M extends QueryMethod> AotRepositoryBuilder forRepository(RepositoryInformation repositoryInformation,
@@ -89,14 +91,14 @@ public AotRepositoryBuilder withConstructorCustomizer(
8991
}
9092

9193
public AotRepositoryBuilder withQueryMethodContributor(
92-
BiFunction<Method, RepositoryInformation, @Nullable MethodContributor<? extends QueryMethod>> methodContributorFunction) {
94+
Function<Method, @Nullable MethodContributor<? extends QueryMethod>> methodContributorFunction) {
9395
this.methodContributorFunction = methodContributorFunction;
9496
return this;
9597
}
9698

97-
public AotRepositoryBuilder withClassCustomizer(ClassCustomizer classCustomizer) {
99+
public AotRepositoryBuilder withClassCustomizer(Consumer<AotRepositoryClassBuilder> classCustomizer) {
98100

99-
this.customizer = classCustomizer;
101+
this.classCustomizer = classCustomizer;
100102
return this;
101103
}
102104

@@ -110,7 +112,7 @@ public AotBundle build() {
110112
repositoryInformation.getRepositoryInterface());
111113

112114
// create the constructor
113-
AotRepositoryConstructorBuilder constructorBuilder = new AotRepositoryConstructorBuilder(repositoryInformation,
115+
RepositoryConstructorBuilder constructorBuilder = new RepositoryConstructorBuilder(
114116
generationMetadata);
115117
if (constructorCustomizer != null) {
116118
constructorCustomizer.accept(constructorBuilder);
@@ -144,7 +146,12 @@ public AotBundle build() {
144146
generationMetadata.getFields().values().forEach(builder::addField);
145147

146148
// finally customize the file itself
147-
this.customizer.customize(repositoryInformation, builder);
149+
this.classCustomizer.accept(customizer -> {
150+
151+
Assert.notNull(customizer, "ClassCustomizer must not be null");
152+
customizer.customize(builder);
153+
});
154+
148155
JavaFile javaFile = JavaFile.builder(packageName(), builder.build()).build();
149156

150157
// TODO: module identifier
@@ -173,8 +180,7 @@ private void contributeMethod(Method method, RepositoryComposition repositoryCom
173180

174181
if (repositoryInformation.isQueryMethod(method) && methodContributorFunction != null) {
175182

176-
MethodContributor<? extends QueryMethod> contributor = methodContributorFunction.apply(method,
177-
repositoryInformation);
183+
MethodContributor<? extends QueryMethod> contributor = methodContributorFunction.apply(method);
178184

179185
if (contributor != null) {
180186

@@ -234,20 +240,6 @@ public ProjectionFactory getProjectionFactory() {
234240
return projectionFactory;
235241
}
236242

237-
/**
238-
* Customizer interface to customize the AOT repository fragment class after it has been defined.
239-
*/
240-
public interface ClassCustomizer {
241-
242-
/**
243-
* Apply customization ot the AOT repository fragment class after it has been defined..
244-
*
245-
* @param information the repository information that is used for the AOT fragment.
246-
* @param builder the class builder to be customized.
247-
*/
248-
void customize(RepositoryInformation information, TypeSpec.Builder builder);
249-
250-
}
251243

252244
record AotBundle(JavaFile javaFile, JSONObject metadata) {
253245
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.repository.aot.generate;
17+
18+
import org.springframework.javapoet.TypeSpec;
19+
20+
/**
21+
* Builder for AOT repository fragment classes.
22+
*
23+
* @author Mark Paluch
24+
* @since 4.0
25+
*/
26+
public interface AotRepositoryClassBuilder {
27+
28+
/**
29+
* Add a class customizer. Customizer is invoked after building the class.
30+
*
31+
* @param customizer the customizer with direct access to the {@link TypeSpec.Builder type builder}.
32+
*/
33+
void customize(ClassCustomizer customizer);
34+
35+
/**
36+
* Customizer interface to customize the AOT repository fragment class after it has been defined.
37+
*/
38+
interface ClassCustomizer {
39+
40+
/**
41+
* Apply customization ot the AOT repository fragment class after it has been defined.
42+
*
43+
* @param builder the class builder to be customized.
44+
*/
45+
void customize(TypeSpec.Builder builder);
46+
47+
}
48+
}

src/main/java/org/springframework/data/repository/aot/generate/AotRepositoryConstructorBuilder.java

+7-64
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,7 @@
1515
*/
1616
package org.springframework.data.repository.aot.generate;
1717

18-
import java.util.Map.Entry;
19-
20-
import javax.lang.model.element.Modifier;
21-
22-
import org.springframework.core.ResolvableType;
23-
import org.springframework.data.repository.aot.generate.AotRepositoryFragmentMetadata.ConstructorArgument;
24-
import org.springframework.data.repository.core.RepositoryInformation;
2518
import org.springframework.javapoet.MethodSpec;
26-
import org.springframework.javapoet.ParameterizedTypeName;
2719
import org.springframework.javapoet.TypeName;
2820

2921
/**
@@ -33,43 +25,23 @@
3325
* @author Mark Paluch
3426
* @since 4.0
3527
*/
36-
public class AotRepositoryConstructorBuilder {
37-
38-
private final RepositoryInformation repositoryInformation;
39-
private final AotRepositoryFragmentMetadata metadata;
40-
41-
private ConstructorCustomizer customizer = (info, builder) -> {};
42-
43-
AotRepositoryConstructorBuilder(RepositoryInformation repositoryInformation, AotRepositoryFragmentMetadata metadata) {
44-
45-
this.repositoryInformation = repositoryInformation;
46-
this.metadata = metadata;
47-
}
28+
public interface AotRepositoryConstructorBuilder {
4829

4930
/**
5031
* Add constructor parameter and create a field storing its value.
5132
*
5233
* @param parameterName name of the parameter.
5334
* @param type parameter type.
5435
*/
55-
public void addParameter(String parameterName, Class<?> type) {
56-
57-
ResolvableType resolvableType = ResolvableType.forClass(type);
58-
if (!resolvableType.hasGenerics() || !resolvableType.hasResolvableGenerics()) {
59-
addParameter(parameterName, TypeName.get(type));
60-
return;
61-
}
62-
63-
addParameter(parameterName, ParameterizedTypeName.get(type, resolvableType.resolveGenerics()));
64-
}
36+
void addParameter(String parameterName, Class<?> type);
6537

6638
/**
6739
* Add constructor parameter and create a field storing its value.
6840
*
6941
* @param parameterName name of the parameter.
7042
* @param type parameter type.
7143
*/
72-
public void addParameter(String parameterName, TypeName type) {
44+
default void addParameter(String parameterName, TypeName type) {
7345
addParameter(parameterName, type, true);
7446
}
7547

@@ -80,56 +52,27 @@ public void addParameter(String parameterName, TypeName type) {
8052
* @param type parameter type.
8153
* @param createField whether to create a field for the parameter and assign its value to the field.
8254
*/
83-
public void addParameter(String parameterName, TypeName type, boolean createField) {
84-
85-
this.metadata.addConstructorArgument(parameterName, type, createField ? parameterName : null);
86-
87-
if (createField) {
88-
this.metadata.addField(parameterName, type, Modifier.PRIVATE, Modifier.FINAL);
89-
}
90-
}
55+
void addParameter(String parameterName, TypeName type, boolean createField);
9156

9257
/**
9358
* Add constructor customizer. Customizer is invoked after adding constructor arguments and before assigning
9459
* constructor arguments to fields.
9560
*
9661
* @param customizer the customizer with direct access to the {@link MethodSpec.Builder constructor builder}.
9762
*/
98-
public void customize(ConstructorCustomizer customizer) {
99-
this.customizer = customizer;
100-
}
101-
102-
MethodSpec buildConstructor() {
103-
104-
MethodSpec.Builder builder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
105-
106-
for (Entry<String, ConstructorArgument> parameter : this.metadata.getConstructorArguments().entrySet()) {
107-
builder.addParameter(parameter.getValue().typeName(), parameter.getKey());
108-
}
109-
110-
customizer.customize(repositoryInformation, builder);
111-
112-
for (Entry<String, ConstructorArgument> parameter : this.metadata.getConstructorArguments().entrySet()) {
113-
if (parameter.getValue().isForLocalField()) {
114-
builder.addStatement("this.$N = $N", parameter.getKey(), parameter.getKey());
115-
}
116-
}
117-
118-
return builder.build();
119-
}
63+
void customize(ConstructorCustomizer customizer);
12064

12165
/**
12266
* Customizer for the AOT repository constructor.
12367
*/
124-
public interface ConstructorCustomizer {
68+
interface ConstructorCustomizer {
12569

12670
/**
12771
* Customize the constructor.
12872
*
129-
* @param information the repository information that is used for the AOT fragment.
13073
* @param builder the constructor builder to be customized.
13174
*/
132-
void customize(RepositoryInformation information, MethodSpec.Builder builder);
75+
void customize(MethodSpec.Builder builder);
13376

13477
}
13578

0 commit comments

Comments
 (0)