Skip to content

Commit ae9d42e

Browse files
Add AOT r2dbc repository support.
We now use the AOT infrastructure of Spring Framework 6 and data commons to provide AOT support building the foundation for native image compilation. Additionally we register hints for GraalVM native image. Also update r2dbc auditing configuration to avoid inner bean definitions.
1 parent 6943cfa commit ae9d42e

File tree

3 files changed

+102
-13
lines changed

3 files changed

+102
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2022 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.r2dbc.aot;
17+
18+
import java.util.Arrays;
19+
20+
import org.springframework.aot.hint.MemberCategory;
21+
import org.springframework.aot.hint.RuntimeHints;
22+
import org.springframework.aot.hint.RuntimeHintsRegistrar;
23+
import org.springframework.aot.hint.TypeReference;
24+
import org.springframework.data.r2dbc.mapping.event.AfterConvertCallback;
25+
import org.springframework.data.r2dbc.mapping.event.AfterSaveCallback;
26+
import org.springframework.data.r2dbc.mapping.event.BeforeConvertCallback;
27+
import org.springframework.data.r2dbc.mapping.event.BeforeSaveCallback;
28+
import org.springframework.data.r2dbc.repository.support.SimpleR2dbcRepository;
29+
30+
/**
31+
* @author Christoph Strobl
32+
* @since 3.0
33+
*/
34+
public class R2dbcRuntimeHints implements RuntimeHintsRegistrar {
35+
36+
@Override
37+
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
38+
39+
hints.reflection().registerTypes(Arrays.asList(
40+
TypeReference.of(SimpleR2dbcRepository.class),
41+
TypeReference.of(AfterConvertCallback.class),
42+
TypeReference.of(BeforeConvertCallback.class),
43+
TypeReference.of(BeforeSaveCallback.class),
44+
TypeReference.of(AfterSaveCallback.class)
45+
),
46+
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS));
47+
}
48+
}

spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/config/R2dbcAuditingRegistrar.java

+52-13
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,26 @@
1717

1818
import java.lang.annotation.Annotation;
1919

20+
import org.springframework.beans.factory.ListableBeanFactory;
2021
import org.springframework.beans.factory.config.BeanDefinition;
21-
import org.springframework.beans.factory.support.AbstractBeanDefinition;
2222
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
23+
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
2324
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
2425
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
2526
import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler;
2627
import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport;
2728
import org.springframework.data.auditing.config.AuditingConfiguration;
2829
import org.springframework.data.config.ParsingUtils;
30+
import org.springframework.data.mapping.context.PersistentEntities;
2931
import org.springframework.data.r2dbc.mapping.event.ReactiveAuditingEntityCallback;
32+
import org.springframework.lang.Nullable;
3033
import org.springframework.util.Assert;
3134

3235
/**
3336
* {@link ImportBeanDefinitionRegistrar} to enable {@link EnableR2dbcAuditing} annotation.
3437
*
3538
* @author Mark Paluch
39+
* @author Christoph Strobl
3640
* @since 1.2
3741
*/
3842
class R2dbcAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
@@ -55,6 +59,12 @@ protected String getAuditingHandlerBeanName() {
5559
return "r2dbcAuditingHandler";
5660
}
5761

62+
@Override
63+
protected void postProcess(BeanDefinitionBuilder builder, AuditingConfiguration configuration,
64+
BeanDefinitionRegistry registry) {
65+
potentiallyRegisterR2dbcPersistentEntities(builder, registry);
66+
}
67+
5868
/*
5969
* (non-Javadoc)
6070
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditHandlerBeanDefinitionBuilder(org.springframework.data.auditing.config.AuditingConfiguration)
@@ -64,13 +74,8 @@ protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingCon
6474

6575
Assert.notNull(configuration, "AuditingConfiguration must not be null");
6676

67-
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveIsNewAwareAuditingHandler.class);
68-
69-
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntitiesFactoryBean.class);
70-
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
71-
72-
builder.addConstructorArgValue(definition.getBeanDefinition());
73-
return configureDefaultAuditHandlerAttributes(configuration, builder);
77+
return configureDefaultAuditHandlerAttributes(configuration,
78+
BeanDefinitionBuilder.rootBeanDefinition(ReactiveIsNewAwareAuditingHandler.class));
7479
}
7580

7681
/*
@@ -84,13 +89,47 @@ protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandle
8489
Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null");
8590
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
8691

87-
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class);
92+
BeanDefinitionBuilder listenerBeanDefinitionBuilder = BeanDefinitionBuilder
93+
.rootBeanDefinition(ReactiveAuditingEntityCallback.class);
94+
listenerBeanDefinitionBuilder
95+
.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
96+
97+
registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder.getBeanDefinition(),
98+
ReactiveAuditingEntityCallback.class.getName(), registry);
99+
}
100+
101+
static void potentiallyRegisterR2dbcPersistentEntities(BeanDefinitionBuilder builder,
102+
BeanDefinitionRegistry registry) {
103+
104+
String persistentEntitiesBeanName = R2dbcAuditingRegistrar.detectPersistentEntitiesBeanName(registry);
105+
106+
if (persistentEntitiesBeanName == null) {
107+
108+
persistentEntitiesBeanName = BeanDefinitionReaderUtils.uniqueBeanName("r2dbcPersistentEntities", registry);
109+
110+
// TODO: https://github.com/spring-projects/spring-framework/issues/28728
111+
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntities.class) //
112+
.setFactoryMethod("of") //
113+
.addConstructorArgReference("r2dbcMappingContext");
114+
115+
registry.registerBeanDefinition(persistentEntitiesBeanName, definition.getBeanDefinition());
116+
}
117+
118+
builder.addConstructorArgReference(persistentEntitiesBeanName);
119+
}
120+
121+
@Nullable
122+
private static String detectPersistentEntitiesBeanName(BeanDefinitionRegistry registry) {
88123

89-
builder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
90-
builder.getRawBeanDefinition().setSource(auditingHandlerDefinition.getSource());
124+
if (registry instanceof ListableBeanFactory beanFactory) {
125+
for (String bn : beanFactory.getBeanNamesForType(PersistentEntities.class)) {
126+
if (bn.startsWith("r2dbc")) {
127+
return bn;
128+
}
129+
}
130+
}
91131

92-
registerInfrastructureBeanWithId(builder.getBeanDefinition(), ReactiveAuditingEntityCallback.class.getName(),
93-
registry);
132+
return null;
94133
}
95134

96135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.aot.hint.RuntimeHintsRegistrar=\
2+
org.springframework.data.r2dbc.aot.R2dbcRuntimeHints

0 commit comments

Comments
 (0)