Skip to content

Commit 06a0d31

Browse files
committed
Polishing.
Refine AotContext construction introducing a builder. Refine TypeCollector construction. See #3474 Original pull request: #3475
1 parent 9e8ed1c commit 06a0d31

8 files changed

Lines changed: 215 additions & 84 deletions

File tree

src/main/java/org/springframework/data/aot/AotContext.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.core.env.Environment;
3737
import org.springframework.core.env.EnvironmentCapable;
3838
import org.springframework.core.env.StandardEnvironment;
39+
import org.springframework.data.util.TypeCollector;
3940
import org.springframework.data.util.TypeScanner;
4041
import org.springframework.util.Assert;
4142
import org.springframework.util.StringUtils;
@@ -67,7 +68,6 @@ public interface AotContext extends EnvironmentCapable {
6768
static AotContext from(BeanFactory beanFactory) {
6869

6970
Assert.notNull(beanFactory, "BeanFactory must not be null");
70-
7171
return new DefaultAotContext(beanFactory, new StandardEnvironment());
7272
}
7373

@@ -87,6 +87,13 @@ static AotContext from(BeanFactory beanFactory, Environment environment) {
8787
return new DefaultAotContext(beanFactory, environment);
8888
}
8989

90+
/**
91+
* Create a {@code AotContext} builder.
92+
*/
93+
public static AotContextBuilder builder() {
94+
return new DefaultAotContextBuilder();
95+
}
96+
9097
/**
9198
* Checks if repository code generation is enabled for a given module by checking environment variables for general
9299
* enablement ({@link #GENERATED_REPOSITORIES_ENABLED}) and store-specific ones following the pattern
@@ -270,6 +277,47 @@ default void typeConfiguration(ResolvableType resolvableType, Consumer<AotTypeCo
270277
*/
271278
void contributeTypeConfigurations(GenerationContext generationContext);
272279

280+
/**
281+
* Builder to create {@link AotContext} instances.
282+
*
283+
* @since 4.0.5
284+
*/
285+
interface AotContextBuilder {
286+
287+
/**
288+
* Configure the {@link BeanFactory} to use. Must be provided.
289+
*
290+
* @param beanFactory the bean factory to use.
291+
* @return this builder.
292+
*/
293+
AotContextBuilder beanFactory(BeanFactory beanFactory);
294+
295+
/**
296+
* Configure the {@link Environment} to use. Defaults to {@link StandardEnvironment} if not configured.
297+
*
298+
* @param environment the environment to use.
299+
* @return this builder.
300+
*/
301+
AotContextBuilder environment(Environment environment);
302+
303+
/**
304+
* Provide a consumer to customize {@link TypeCollector}.
305+
*
306+
* @param typeCollectorConsumer the consumer to configure {@link TypeCollector}.
307+
* @return this builder.
308+
*/
309+
AotContextBuilder customizeTypeCollector(Consumer<TypeCollector> typeCollectorConsumer);
310+
311+
/**
312+
* Build the {@link AotContext} to use. Building the AotContext requires {@link #beanFactory(BeanFactory)} to be
313+
* configured.
314+
*
315+
* @return the build {@link AotContext} to use.
316+
*/
317+
AotContext build();
318+
319+
}
320+
273321
/**
274322
* Type-based introspector to resolve {@link Class} from a type name and to introspect the bean factory for presence
275323
* of beans.

src/main/java/org/springframework/data/aot/AotMappingContext.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.data.mapping.model.EntityInstantiators;
3737
import org.springframework.data.mapping.model.Property;
3838
import org.springframework.data.mapping.model.SimpleTypeHolder;
39+
import org.springframework.data.util.Lazy;
3940
import org.springframework.data.util.TypeCollector;
4041

4142
/**
@@ -48,17 +49,18 @@
4849
class AotMappingContext extends
4950
AbstractMappingContext<BasicPersistentEntity<?, AotMappingContext.AotPersistentProperty>, AotMappingContext.AotPersistentProperty> {
5051

52+
private final static Lazy<TypeCollector> DEFAULT_TYPE_COLLECTOR = Lazy.of(TypeCollector::new);
5153
private final EntityInstantiators instantiators = new EntityInstantiators();
5254
private final AotAccessorFactory propertyAccessorFactory = new AotAccessorFactory();
5355
private final Predicate<Class<?>> typeCollectorFilter;
5456

5557
AotMappingContext() {
56-
this(TypeCollector.typeFilter(typeCollector -> {}));
58+
this(DEFAULT_TYPE_COLLECTOR.get().getTypeFilter());
5759
}
5860

5961
/**
60-
* @param typeFilter used for filtering during {@link #shouldCreatePersistentEntityFor(TypeInformation)}
61-
* @since 4.1
62+
* @param typeFilter used for filtering during {@link #shouldCreatePersistentEntityFor(TypeInformation)}.
63+
* @since 4.0.5
6264
*/
6365
AotMappingContext(Predicate<Class<?>> typeFilter) {
6466
this.typeCollectorFilter = typeFilter;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2026-present 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.aot;
17+
18+
import java.util.function.Consumer;
19+
20+
import org.jspecify.annotations.Nullable;
21+
22+
import org.springframework.beans.factory.BeanFactory;
23+
import org.springframework.core.env.Environment;
24+
import org.springframework.core.env.StandardEnvironment;
25+
import org.springframework.data.util.TypeCollector;
26+
import org.springframework.util.Assert;
27+
28+
/**
29+
* Default implementation of {@link AotContext.AotContextBuilder}.
30+
*
31+
* @author Mark Paluch
32+
* @since 4.0.5
33+
*/
34+
class DefaultAotContextBuilder implements AotContext.AotContextBuilder {
35+
36+
private @Nullable BeanFactory beanFactory;
37+
38+
private @Nullable Environment environment;
39+
40+
private Consumer<TypeCollector> typeCollectorConsumer = it -> {};
41+
42+
@Override
43+
public AotContext.AotContextBuilder beanFactory(BeanFactory beanFactory) {
44+
this.beanFactory = beanFactory;
45+
return this;
46+
}
47+
48+
@Override
49+
public AotContext.AotContextBuilder environment(Environment environment) {
50+
this.environment = environment;
51+
return this;
52+
}
53+
54+
@Override
55+
public AotContext.AotContextBuilder customizeTypeCollector(Consumer<TypeCollector> typeCollectorConsumer) {
56+
this.typeCollectorConsumer = typeCollectorConsumer;
57+
return this;
58+
}
59+
60+
@Override
61+
public AotContext build() {
62+
63+
Assert.notNull(this.beanFactory, "BeanFactory must not be null");
64+
65+
Environment environment = this.environment;
66+
if (environment == null) {
67+
environment = new StandardEnvironment();
68+
}
69+
70+
AotMappingContext mappingContext = new AotMappingContext(
71+
TypeCollector.create(typeCollectorConsumer).getTypeFilter());
72+
return new DefaultAotContext(beanFactory, environment, mappingContext);
73+
}
74+
75+
}

src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public void setEnvironment(Environment environment) {
8484

8585
DefaultAotContext aotContext = new DefaultAotContext(registeredBean.getBeanFactory(),
8686
getConfiguredEnvironmentOrTryToResolveOne(registeredBean),
87-
new AotMappingContext(TypeCollector.typeFilter(typeCollectorCustomizer())));
87+
new AotMappingContext(TypeCollector.create(typeCollectorCustomizer()).getTypeFilter()));
8888
return contribute(aotContext, resolveManagedTypes(registeredBean), registeredBean);
8989
}
9090

src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotProcessor.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Map;
2222
import java.util.Optional;
2323
import java.util.Set;
24+
import java.util.function.Consumer;
2425
import java.util.stream.Stream;
2526

2627
import org.apache.commons.logging.Log;
@@ -51,6 +52,7 @@
5152
import org.springframework.data.repository.core.RepositoryInformation;
5253
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
5354
import org.springframework.data.repository.core.support.RepositoryFragment;
55+
import org.springframework.data.util.TypeCollector;
5456
import org.springframework.data.util.TypeContributor;
5557
import org.springframework.data.util.TypeUtils;
5658
import org.springframework.util.Assert;
@@ -274,6 +276,16 @@ protected void configureTypeContribution(Class<?> type, AotContext aotContext) {
274276
aotContext.typeConfiguration(type, config -> config.forDataBinding().contributeAccessors().forQuerydsl());
275277
}
276278

279+
/**
280+
* Customization hook to configure {@link TypeCollector}.
281+
*
282+
* @return a {@link Consumer} to customize the {@link TypeCollector}, must not be {@literal null}.
283+
* @since 4.0
284+
*/
285+
protected Consumer<TypeCollector> typeCollectorCustomizer() {
286+
return typeCollector -> {};
287+
}
288+
277289
/**
278290
* This method allows for the creation to be overridden by subclasses.
279291
*
@@ -344,10 +356,13 @@ private static void registerReflectiveHints(Class<?> typeToRegister, GenerationC
344356
.formatted(bean.getBeanName()));
345357
return null;
346358
}
359+
360+
AotContext aotContext = AotContext.builder().beanFactory(bean.getBeanFactory()).environment(environment)
361+
.customizeTypeCollector(typeCollectorCustomizer()).build();
362+
347363
RepositoryInformation repositoryInformation = reader.getRepositoryInformation();
348364
DefaultAotRepositoryContext repositoryContext = new DefaultAotRepositoryContext(bean, repositoryInformation,
349-
extension.getModuleName(), AotContext.from(bean.getBeanFactory(), environment),
350-
configuration.getConfigurationSource());
365+
extension.getModuleName(), aotContext, configuration.getConfigurationSource());
351366

352367
repositoryContext.setIdentifyingAnnotations(extension.getIdentifyingAnnotations());
353368

0 commit comments

Comments
 (0)