Skip to content

Commit a313db7

Browse files
Add documentation and fix issues after rebase
1 parent 274986b commit a313db7

File tree

7 files changed

+91
-31
lines changed

7 files changed

+91
-31
lines changed

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

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/*
2-
* Copyright 2025. the original author or authors.
2+
* Copyright 2025-present the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* https://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -31,27 +31,73 @@
3131
import org.springframework.data.projection.TargetAware;
3232

3333
/**
34+
* Configuration object that captures various AOT configuration aspects of types within the data context by offering
35+
* predefined methods to register native configuration necessary for data binding, projection proxy definitions, AOT
36+
* cglib bytecode generation and other common tasks.
37+
* <p>
38+
* On {@link #contribute(Environment, GenerationContext)} the configuration is added to the {@link GenerationContext}.
39+
*
3440
* @author Christoph Strobl
41+
* @since 4.0
3542
*/
3643
public interface AotTypeConfiguration {
3744

45+
/**
46+
* Configure the referenced type for data binding. In case of {@link java.lang.annotation.Annotation} only data ones
47+
* are considered. For more fine grained control use {@link #forReflectiveAccess(MemberCategory...)}.
48+
*
49+
* @return this.
50+
*/
3851
AotTypeConfiguration forDataBinding();
3952

53+
/**
54+
* Configure the referenced type for reflective access by providing at least one {@link MemberCategory}.
55+
*
56+
* @param categories must not contain {@literal null}.
57+
* @return this.
58+
*/
4059
AotTypeConfiguration forReflectiveAccess(MemberCategory... categories);
4160

61+
/**
62+
* Contribute generated cglib accessors for the referenced type.
63+
* <p>
64+
* Can be disabled by user configuration ({@code spring.aot.data.accessors.enabled}). Honors in/exclusions set by user
65+
* configuration {@code spring.aot.data.accessors.include} / {@code spring.aot.data.accessors.exclude}
66+
*
67+
* @return this.
68+
*/
4269
AotTypeConfiguration contributeAccessors();
4370

4471
// TODO: ? should this be a global condition for the entire configuration or do we need it for certain aspects ?
4572
AotTypeConfiguration filter(Predicate<Class<?>> filter);
4673

74+
/**
75+
* Configure the referenced type as a projection interface returned by eg. a query method.
76+
* <p>
77+
* Shortcut for {@link #proxyInterface(Class[]) proxyInterface(TargetAware, SpringProxy, DecoratingProxy)}
78+
*
79+
* @return this.
80+
*/
4781
default AotTypeConfiguration usedAsProjectionInterface() {
4882
return proxyInterface(TargetAware.class, SpringProxy.class, DecoratingProxy.class);
4983
}
5084

85+
/**
86+
* Configure the referenced type as a spring proxy interface.
87+
* <p>
88+
* Shortcut for {@link #proxyInterface(Class[]) proxyInterface(SpringProxy, Advised, DecoratingProxy)}
89+
*
90+
* @return this.
91+
*/
5192
default AotTypeConfiguration springProxy() {
5293
return proxyInterface(SpringProxy.class, Advised.class, DecoratingProxy.class);
5394
}
5495

96+
/**
97+
* Configure the referenced type as a repository proxy.
98+
*
99+
* @return this.
100+
*/
55101
default AotTypeConfiguration repositoryProxy() {
56102

57103
springProxy();
@@ -67,14 +113,36 @@ default AotTypeConfiguration repositoryProxy() {
67113
return this;
68114
}
69115

116+
/**
117+
* Register a proxy for the referenced type that also implements the given proxyInterfaces.
118+
*
119+
* @param proxyInterfaces additional interfaces the proxy implements. Order matters!
120+
* @return this.
121+
*/
70122
AotTypeConfiguration proxyInterface(List<TypeReference> proxyInterfaces);
71123

124+
/**
125+
* Register a proxy for the referenced type that also implements the given proxyInterfaces.
126+
*
127+
* @param proxyInterfaces additional interfaces the proxy implements. Order matters!
128+
* @return this.
129+
*/
72130
default AotTypeConfiguration proxyInterface(Class<?>... proxyInterfaces) {
73131
return proxyInterface(Stream.of(proxyInterfaces).map(TypeReference::of).toList());
74132
}
75133

134+
/**
135+
* Configure the referenced type for usage with Querydsl by registering hints for potential {@code Q} types.
136+
*
137+
* @return this.
138+
*/
76139
AotTypeConfiguration forQuerydsl();
77140

141+
/**
142+
* Write the configuration to the given {@link GenerationContext}.
143+
*
144+
* @param environment must not be {@literal null}.
145+
* @param generationContext must not be {@literal null}.
146+
*/
78147
void contribute(Environment environment, GenerationContext generationContext);
79-
80148
}

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import java.util.stream.Stream;
3131

3232
import org.jspecify.annotations.Nullable;
33-
3433
import org.springframework.aot.generate.GenerationContext;
3534
import org.springframework.aot.hint.MemberCategory;
3635
import org.springframework.aot.hint.TypeReference;
@@ -41,8 +40,6 @@
4140
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
4241
import org.springframework.beans.factory.support.RootBeanDefinition;
4342
import org.springframework.core.env.Environment;
44-
import org.springframework.core.env.Environment;
45-
import org.springframework.data.mapping.context.MappingContext;
4643
import org.springframework.data.util.QTypeContributor;
4744
import org.springframework.data.util.TypeContributor;
4845
import org.springframework.util.AntPathMatcher;
@@ -53,22 +50,28 @@
5350
* Default {@link AotContext} implementation.
5451
*
5552
* @author Mark Paluch
53+
* @author Christoph Strobl
5654
* @since 3.0
5755
*/
5856
class DefaultAotContext implements AotContext {
5957

60-
private final AotMappingContext mappingContext = new AotMappingContext();;
58+
private final AotMappingContext mappingContext;
6159
private final ConfigurableListableBeanFactory factory;
6260

6361
// TODO: should we reuse the config or potentially have multiple ones with different settings - somehow targets the
6462
// filtering issue
6563
private final Map<Class<?>, AotTypeConfiguration> typeConfigurations = new HashMap<>();
66-
private final Environment environment;
64+
private final Environment environment;
6765

6866
public DefaultAotContext(BeanFactory beanFactory, Environment environment) {
67+
this(beanFactory, environment, new AotMappingContext());
68+
}
69+
70+
DefaultAotContext(BeanFactory beanFactory, Environment environment, AotMappingContext mappingContext) {
6971
this.factory = beanFactory instanceof ConfigurableListableBeanFactory cbf ? cbf
7072
: new DefaultListableBeanFactory(beanFactory);
7173
this.environment = environment;
74+
this.mappingContext = mappingContext;
7275
}
7376

7477
@Override
@@ -255,11 +258,7 @@ public void contribute(Environment environment, GenerationContext generationCont
255258
}
256259

257260
if (forDataBinding) {
258-
259261
TypeContributor.contribute(type, Set.of(TypeContributor.DATA_NAMESPACE), generationContext);
260-
261-
generationContext.getRuntimeHints().reflection().registerType(type, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
262-
MemberCategory.INVOKE_DECLARED_METHODS);
263262
}
264263

265264
if (forQuerydsl) {
@@ -268,9 +267,8 @@ public void contribute(Environment environment, GenerationContext generationCont
268267

269268
if (!proxies.isEmpty()) {
270269
for (List<TypeReference> proxyInterfaces : proxies) {
271-
generationContext.getRuntimeHints().proxies()
272-
.registerJdkProxy(Stream.concat(Stream.of(TypeReference.of(type)), proxyInterfaces.stream())
273-
.toArray(TypeReference[]::new));
270+
generationContext.getRuntimeHints().proxies().registerJdkProxy(
271+
Stream.concat(Stream.of(TypeReference.of(type)), proxyInterfaces.stream()).toArray(TypeReference[]::new));
274272
}
275273
}
276274

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,6 @@ public void setEnvironment(Environment environment) {
7070
this.environment = Lazy.of(environment);
7171
}
7272

73-
@Override
74-
public void setEnvironment(Environment environment) {
75-
this.environment = Lazy.of(() -> environment);
76-
}
77-
7873
@Override
7974
public @Nullable BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
8075

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
7777

7878
private static final String KOTLIN_COROUTINE_REPOSITORY_TYPE_NAME = "org.springframework.data.repository.kotlin.CoroutineCrudRepository";
7979

80-
private final RepositoryRegistrationAotProcessor repositoryRegistrationAotProcessor;
81-
8280
private final RepositoryRegistrationAotProcessor aotProcessor;
8381

8482
private final AotRepositoryContext repositoryContext;
@@ -165,6 +163,10 @@ protected RepositoryRegistrationAotContribution(RepositoryRegistrationAotProcess
165163
return new RepositoryRegistrationAotContribution(getRepositoryRegistrationAotProcessor(), repositoryContext);
166164
}
167165

166+
protected @Nullable BiFunction<AotRepositoryContext, GenerationContext, @Nullable RepositoryContributor> getModuleContribution() {
167+
return this.moduleContribution;
168+
}
169+
168170
protected AotRepositoryContext getRepositoryContext() {
169171
return this.repositoryContext;
170172
}
@@ -232,9 +234,11 @@ public void applyTo(GenerationContext generationContext, BeanRegistrationCode be
232234
this.repositoryContributor = moduleContribution.apply(getRepositoryContext(), generationContext);
233235

234236
if (this.repositoryContributor != null) {
235-
this.repositoryContributor.contribute(environment.get(), generationContext);
237+
this.repositoryContributor.contribute(generationContext);
236238
}
237239
}
240+
getRepositoryContext().typeConfigurations()
241+
.forEach(typeConfiguration -> typeConfiguration.contribute(environment.get(), generationContext));
238242
}
239243

240244
@Override

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ protected ConfigurableListableBeanFactory getBeanFactory() {
196196

197197
protected void contributeType(Class<?> type, GenerationContext generationContext) {
198198
TypeContributor.contribute(type, it -> true, generationContext);
199-
200199
}
201200

202201
protected Log getLogger() {

src/test/java/org/springframework/data/aot/AotContextUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ void shouldApplyIncludeExcludeFilters() {
9999

100100
private void contributeAccessor(Class<?>... classes) {
101101

102-
DefaultAotContext context = new DefaultAotContext(beanFactory, mockEnvironment);
102+
DefaultAotContext context = new DefaultAotContext(beanFactory, mockEnvironment, mappingContext);
103103

104104
for (Class<?> aClass : classes) {
105105
context.typeConfiguration(aClass, AotTypeConfiguration::contributeAccessors);

src/test/java/org/springframework/data/repository/aot/generate/DummyModuleAotRepositoryContext.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Collection;
2121
import java.util.List;
2222
import java.util.Set;
23+
import java.util.function.Consumer;
2324

2425
import org.jspecify.annotations.Nullable;
2526

@@ -79,13 +80,8 @@ public IntrospectedBeanDefinition introspectBeanDefinition(String beanName) {
7980
}
8081

8182
@Override
82-
public InstantiationCreator instantiationCreator(TypeReference typeReference) {
83-
return null;
84-
}
83+
public void typeConfiguration(Class<?> type, Consumer<AotTypeConfiguration> configurationConsumer) {
8584

86-
@Override
87-
public AotTypeConfiguration typeConfiguration(TypeReference typeReference) {
88-
return null;
8985
}
9086

9187
@Override

0 commit comments

Comments
 (0)