2929import org .apache .commons .logging .Log ;
3030import org .apache .commons .logging .LogFactory ;
3131import org .jspecify .annotations .Nullable ;
32-
33- import org .springframework .aot .generate .ClassNameGenerator ;
3432import org .springframework .aot .generate .Generated ;
33+ import org .springframework .aot .generate .GeneratedTypeReference ;
34+ import org .springframework .aot .hint .TypeReference ;
3535import org .springframework .data .projection .ProjectionFactory ;
3636import org .springframework .data .repository .aot .generate .AotRepositoryFragmentMetadata .ConstructorArgument ;
3737import org .springframework .data .repository .core .RepositoryInformation ;
3838import org .springframework .data .repository .core .support .RepositoryComposition ;
3939import org .springframework .data .repository .core .support .RepositoryFragment ;
4040import org .springframework .data .repository .query .QueryMethod ;
4141import org .springframework .javapoet .ClassName ;
42- import org .springframework .javapoet .FieldSpec ;
4342import org .springframework .javapoet .JavaFile ;
4443import org .springframework .javapoet .MethodSpec ;
4544import org .springframework .javapoet .TypeName ;
@@ -64,6 +63,8 @@ class AotRepositoryBuilder {
6463 private @ Nullable Consumer <AotRepositoryConstructorBuilder > constructorCustomizer ;
6564 private @ Nullable MethodContributorFactory methodContributorFactory ;
6665 private Consumer <AotRepositoryClassBuilder > classCustomizer ;
66+ private @ Nullable TypeReference targetClassName ;
67+ private RepositoryConstructorBuilder constructorBuilder ;
6768
6869 private AotRepositoryBuilder (RepositoryInformation repositoryInformation , String moduleName ,
6970 ProjectionFactory projectionFactory ) {
@@ -72,13 +73,9 @@ private AotRepositoryBuilder(RepositoryInformation repositoryInformation, String
7273 this .moduleName = moduleName ;
7374 this .projectionFactory = projectionFactory ;
7475
75- this .generationMetadata = new AotRepositoryFragmentMetadata (className ());
76- this .generationMetadata .addField (FieldSpec
77- .builder (TypeName .get (Log .class ), "logger" , Modifier .PRIVATE , Modifier .STATIC , Modifier .FINAL )
78- .initializer ("$T.getLog($T.class)" , TypeName .get (LogFactory .class ), this .generationMetadata .getTargetTypeName ())
79- .build ());
80-
76+ this .generationMetadata = new AotRepositoryFragmentMetadata ();
8177 this .classCustomizer = (builder ) -> {};
78+ this .constructorBuilder = new RepositoryConstructorBuilder (generationMetadata );
8279 }
8380
8481 /**
@@ -131,15 +128,24 @@ public AotRepositoryBuilder withQueryMethodContributor(MethodContributorFactory
131128 return this ;
132129 }
133130
134- public AotBundle build () {
131+ public AotRepositoryBuilder prepare (@ Nullable ClassName targetClassName ) {
132+ if (targetClassName == null ) {
133+ withTargetClassName (null );
134+ } else {
135+ withTargetClassName (GeneratedTypeReference .of (targetClassName ));
136+ }
137+ if (constructorCustomizer != null ) {
138+ constructorCustomizer .accept (constructorBuilder );
139+ }
140+ return this ;
141+ }
142+
143+ public AotBundle build (TypeSpec .Builder builder ) {
135144
136145 List <AotRepositoryMethod > methodMetadata = new ArrayList <>();
137146 RepositoryComposition repositoryComposition = repositoryInformation .getRepositoryComposition ();
138147
139- // start creating the type
140- TypeSpec .Builder builder = TypeSpec .classBuilder (this .generationMetadata .getTargetTypeName ()) //
141- .addModifiers (Modifier .PUBLIC ) //
142- .addAnnotation (Generated .class ) //
148+ builder .addModifiers (Modifier .PUBLIC ) //
143149 .addJavadoc ("AOT generated $L repository implementation for {@link $T}.\n " , moduleName ,
144150 repositoryInformation .getRepositoryInterface ());
145151
@@ -177,15 +183,31 @@ public AotBundle build() {
177183 return new AotBundle (javaFile , metadata );
178184 }
179185
180- private MethodSpec buildConstructor () {
186+ public AotBundle build () {
187+
188+ ClassName className = ClassName
189+ .bestGuess ((targetClassName != null ? targetClassName : intendedTargetClassName ()).getCanonicalName ());
190+ return build (TypeSpec .classBuilder (className ).addAnnotation (Generated .class ));
191+ }
181192
182- RepositoryConstructorBuilder constructorBuilder = new RepositoryConstructorBuilder (
183- generationMetadata );
193+ public TypeReference intendedTargetClassName () {
194+ return TypeReference .of ("%s.%s" .formatted (packageName (), typeName ()));
195+ }
184196
185- if (constructorCustomizer != null ) {
186- constructorCustomizer .accept (constructorBuilder );
197+ public @ Nullable TypeReference actualTargetClassName () {
198+
199+ if (targetClassName == null ) {
200+ return null ;
187201 }
202+ return targetClassName ;
203+ }
188204
205+ AotRepositoryBuilder withTargetClassName (@ Nullable TypeReference targetClassName ) {
206+ this .targetClassName = targetClassName ;
207+ return this ;
208+ }
209+
210+ private MethodSpec buildConstructor () {
189211 return constructorBuilder .buildConstructor ();
190212 }
191213
@@ -252,15 +274,11 @@ public AotRepositoryFragmentMetadata getGenerationMetadata() {
252274 return generationMetadata ;
253275 }
254276
255- private ClassName className () {
256- return new ClassNameGenerator (ClassName .get (packageName (), typeName ())).generateClassName ("Aot" , null );
257- }
258-
259- private String packageName () {
277+ public String packageName () {
260278 return repositoryInformation .getRepositoryInterface ().getPackageName ();
261279 }
262280
263- private String typeName () {
281+ public String typeName () {
264282 return "%sImpl" .formatted (repositoryInformation .getRepositoryInterface ().getSimpleName ());
265283 }
266284
@@ -280,7 +298,6 @@ public ProjectionFactory getProjectionFactory() {
280298 return projectionFactory ;
281299 }
282300
283-
284301 /**
285302 * Customizer interface to customize the AOT repository fragment constructor through
286303 * {@link AotRepositoryConstructorBuilder}.
0 commit comments