Skip to content

Commit 47c1ff5

Browse files
Add AOT support for redis repositories.
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. See: #2350
1 parent 8c40523 commit 47c1ff5

File tree

3 files changed

+158
-18
lines changed

3 files changed

+158
-18
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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.redis.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.lang.Nullable;
25+
26+
/**
27+
* @author Christoph Strobl
28+
* @since 3.0
29+
*/
30+
public class DataRedisRuntimeHints implements RuntimeHintsRegistrar {
31+
32+
@Override
33+
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
34+
35+
// REFLECTION
36+
hints.reflection()
37+
.registerTypes(
38+
Arrays.asList(TypeReference.of(org.springframework.data.redis.connection.RedisConnection.class),
39+
TypeReference.of(org.springframework.data.redis.connection.StringRedisConnection.class),
40+
TypeReference.of(org.springframework.data.redis.connection.DefaultedRedisConnection.class),
41+
TypeReference.of(org.springframework.data.redis.connection.DefaultedRedisClusterConnection.class),
42+
TypeReference.of(org.springframework.data.redis.connection.RedisKeyCommands.class),
43+
TypeReference.of(org.springframework.data.redis.connection.RedisStringCommands.class),
44+
TypeReference.of(org.springframework.data.redis.connection.RedisListCommands.class),
45+
TypeReference.of(org.springframework.data.redis.connection.RedisSetCommands.class),
46+
TypeReference.of(org.springframework.data.redis.connection.RedisZSetCommands.class),
47+
TypeReference.of(org.springframework.data.redis.connection.RedisHashCommands.class),
48+
TypeReference.of(org.springframework.data.redis.connection.RedisTxCommands.class),
49+
TypeReference.of(org.springframework.data.redis.connection.RedisPubSubCommands.class),
50+
TypeReference.of(org.springframework.data.redis.connection.RedisConnectionCommands.class),
51+
TypeReference.of(org.springframework.data.redis.connection.RedisServerCommands.class),
52+
TypeReference.of(org.springframework.data.redis.connection.RedisStreamCommands.class),
53+
TypeReference.of(org.springframework.data.redis.connection.RedisScriptingCommands.class),
54+
TypeReference.of(org.springframework.data.redis.connection.RedisGeoCommands.class),
55+
TypeReference.of(org.springframework.data.redis.connection.RedisHyperLogLogCommands.class),
56+
TypeReference.of(org.springframework.data.redis.connection.RedisClusterCommands.class),
57+
TypeReference.of(org.springframework.data.redis.connection.ReactiveRedisConnection.class),
58+
TypeReference.of(org.springframework.data.redis.connection.ReactiveKeyCommands.class),
59+
TypeReference.of(org.springframework.data.redis.connection.ReactiveStringCommands.class),
60+
TypeReference.of(org.springframework.data.redis.connection.ReactiveListCommands.class),
61+
TypeReference.of(org.springframework.data.redis.connection.ReactiveSetCommands.class),
62+
TypeReference.of(org.springframework.data.redis.connection.ReactiveZSetCommands.class),
63+
TypeReference.of(org.springframework.data.redis.connection.ReactiveHashCommands.class),
64+
TypeReference.of(org.springframework.data.redis.connection.ReactivePubSubCommands.class),
65+
TypeReference.of(org.springframework.data.redis.connection.ReactiveServerCommands.class),
66+
TypeReference.of(org.springframework.data.redis.connection.ReactiveStreamCommands.class),
67+
TypeReference.of(org.springframework.data.redis.connection.ReactiveScriptingCommands.class),
68+
TypeReference.of(org.springframework.data.redis.connection.ReactiveGeoCommands.class),
69+
TypeReference.of(org.springframework.data.redis.connection.ReactiveHyperLogLogCommands.class),
70+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterKeyCommands.class),
71+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterStringCommands.class),
72+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterListCommands.class),
73+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterSetCommands.class),
74+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterZSetCommands.class),
75+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterHashCommands.class),
76+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterServerCommands.class),
77+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterStreamCommands.class),
78+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterScriptingCommands.class),
79+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterGeoCommands.class),
80+
TypeReference.of(org.springframework.data.redis.connection.ReactiveClusterHyperLogLogCommands.class),
81+
TypeReference.of(org.springframework.data.redis.core.ReactiveRedisOperations.class),
82+
TypeReference.of(org.springframework.data.redis.core.ReactiveRedisTemplate.class),
83+
TypeReference.of(org.springframework.data.redis.core.RedisOperations.class),
84+
TypeReference.of(org.springframework.data.redis.core.RedisTemplate.class),
85+
TypeReference.of(org.springframework.data.redis.core.StringRedisTemplate.class),
86+
TypeReference.of(org.springframework.data.keyvalue.annotation.KeySpace.class),
87+
TypeReference.of(org.springframework.data.keyvalue.core.AbstractKeyValueAdapter.class),
88+
TypeReference.of(org.springframework.data.keyvalue.core.KeyValueAdapter.class),
89+
TypeReference.of(org.springframework.data.keyvalue.core.KeyValueOperations.class),
90+
TypeReference.of(org.springframework.data.keyvalue.core.KeyValueTemplate.class),
91+
TypeReference.of(org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext.class),
92+
TypeReference.of(org.springframework.data.keyvalue.repository.KeyValueRepository.class),
93+
TypeReference
94+
.of(org.springframework.data.keyvalue.repository.support.KeyValueRepositoryFactoryBean.class),
95+
TypeReference.of(org.springframework.data.keyvalue.repository.config.QueryCreatorType.class),
96+
TypeReference.of(org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery.class),
97+
TypeReference.of(org.springframework.data.redis.core.RedisKeyValueAdapter.class),
98+
TypeReference.of(org.springframework.data.redis.core.RedisKeyValueTemplate.class),
99+
TypeReference.of(org.springframework.data.redis.core.convert.KeyspaceConfiguration.class),
100+
TypeReference.of(org.springframework.data.redis.core.convert.MappingConfiguration.class),
101+
TypeReference.of(org.springframework.data.redis.core.convert.MappingRedisConverter.class),
102+
TypeReference.of(org.springframework.data.redis.core.convert.RedisConverter.class),
103+
TypeReference.of(org.springframework.data.redis.core.convert.RedisCustomConversions.class),
104+
TypeReference.of(org.springframework.data.redis.core.convert.ReferenceResolver.class),
105+
TypeReference.of(org.springframework.data.redis.core.convert.ReferenceResolverImpl.class),
106+
TypeReference.of(org.springframework.data.redis.core.index.IndexConfiguration.class),
107+
TypeReference.of(org.springframework.data.redis.core.index.ConfigurableIndexDefinitionProvider.class),
108+
TypeReference.of(org.springframework.data.redis.core.mapping.RedisMappingContext.class),
109+
TypeReference.of(org.springframework.data.redis.repository.support.RedisRepositoryFactoryBean.class),
110+
TypeReference.of(org.springframework.data.redis.repository.query.RedisQueryCreator.class)),
111+
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
112+
MemberCategory.INVOKE_PUBLIC_METHODS));
113+
114+
// PROXIES
115+
hints.proxies().registerJdkProxy(TypeReference.of(org.springframework.data.redis.connection.RedisConnection.class));
116+
hints.proxies()
117+
.registerJdkProxy(TypeReference.of(org.springframework.data.redis.connection.DefaultedRedisConnection.class));
118+
hints.proxies()
119+
.registerJdkProxy(TypeReference.of(org.springframework.data.redis.connection.ReactiveRedisConnection.class));
120+
hints.proxies().registerJdkProxy(
121+
TypeReference.of(org.springframework.data.redis.connection.StringRedisConnection.class),
122+
TypeReference.of(org.springframework.data.redis.connection.DecoratedRedisConnection.class));
123+
124+
}
125+
}

src/main/java/org/springframework/data/redis/repository/configuration/RedisRepositoryConfigurationExtension.java

+31-18
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.beans.factory.config.BeanDefinition;
2323
import org.springframework.beans.factory.support.AbstractBeanDefinition;
2424
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
25+
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
2526
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
2627
import org.springframework.beans.factory.support.RootBeanDefinition;
2728
import org.springframework.data.keyvalue.repository.config.KeyValueRepositoryConfigurationExtension;
@@ -51,6 +52,7 @@ public class RedisRepositoryConfigurationExtension extends KeyValueRepositoryCon
5152
private static final String REDIS_REFERENCE_RESOLVER_BEAN_NAME = "redisReferenceResolver";
5253
private static final String REDIS_ADAPTER_BEAN_NAME = "redisKeyValueAdapter";
5354
private static final String REDIS_CUSTOM_CONVERSIONS_BEAN_NAME = "redisCustomConversions";
55+
private static final String REDIS_MAPPING_CONFIG_BEAN_NAME = "redisMappingConfiguration";
5456

5557
@Override
5658
public String getModuleName() {
@@ -77,8 +79,29 @@ public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConf
7779
"@EnableRedisRepositories(redisTemplateRef = … ) must be configured to a non empty value");
7880
}
7981

80-
registerIfNotAlreadyRegistered(() -> createRedisMappingContext(configuration), registry, MAPPING_CONTEXT_BEAN_NAME,
81-
configuration.getSource());
82+
// Mapping config
83+
84+
String mappingConfigBeanName = BeanDefinitionReaderUtils.uniqueBeanName(REDIS_MAPPING_CONFIG_BEAN_NAME, registry);
85+
String indexConfigurationBeanName = BeanDefinitionReaderUtils.uniqueBeanName("redisIndexConfiguration", registry);
86+
String keyspaceConfigurationBeanName = BeanDefinitionReaderUtils.uniqueBeanName("redisKeyspaceConfiguration",
87+
registry);
88+
89+
registerIfNotAlreadyRegistered(() -> BeanDefinitionBuilder
90+
.rootBeanDefinition(configuration.getRequiredAttribute("indexConfiguration", Class.class)) //
91+
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE) //
92+
.getBeanDefinition(), registry, indexConfigurationBeanName, configuration.getSource());
93+
94+
registerIfNotAlreadyRegistered(() -> BeanDefinitionBuilder
95+
.rootBeanDefinition(configuration.getRequiredAttribute("keyspaceConfiguration", Class.class)) //
96+
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE) //
97+
.getBeanDefinition(), registry, keyspaceConfigurationBeanName, configuration.getSource());
98+
99+
registerIfNotAlreadyRegistered(
100+
() -> createMappingConfigBeanDef(indexConfigurationBeanName, keyspaceConfigurationBeanName), registry,
101+
mappingConfigBeanName, configuration.getSource());
102+
103+
registerIfNotAlreadyRegistered(() -> createRedisMappingContext(mappingConfigBeanName), registry,
104+
MAPPING_CONTEXT_BEAN_NAME, configuration.getSource());
82105

83106
// Register custom conversions
84107
registerIfNotAlreadyRegistered(() -> new RootBeanDefinition(RedisCustomConversions.class), registry,
@@ -122,8 +145,7 @@ private static AbstractBeanDefinition createRedisKeyValueAdapter(RepositoryConfi
122145
configuration.getRequiredAttribute("enableKeyspaceEvents", EnableKeyspaceEvents.class)) //
123146
.addPropertyValue("keyspaceNotificationsConfigParameter",
124147
configuration.getAttribute("keyspaceNotificationsConfigParameter", String.class).orElse("")) //
125-
.addPropertyValue("shadowCopy",
126-
configuration.getRequiredAttribute("shadowCopy", ShadowCopy.class)) //
148+
.addPropertyValue("shadowCopy", configuration.getRequiredAttribute("shadowCopy", ShadowCopy.class)) //
127149
.getBeanDefinition();
128150
}
129151

@@ -134,26 +156,17 @@ private static AbstractBeanDefinition createRedisReferenceResolverDefinition(Str
134156
.getBeanDefinition();
135157
}
136158

137-
private static AbstractBeanDefinition createRedisMappingContext(RepositoryConfigurationSource configurationSource) {
159+
private static AbstractBeanDefinition createRedisMappingContext(String mappingConfigRef) {
138160

139161
return BeanDefinitionBuilder.rootBeanDefinition(RedisMappingContext.class) //
140-
.addConstructorArgValue(createMappingConfigBeanDef(configurationSource)) //
141-
.getBeanDefinition();
162+
.addConstructorArgReference(mappingConfigRef).getBeanDefinition();
142163
}
143164

144-
private static BeanDefinition createMappingConfigBeanDef(RepositoryConfigurationSource configuration) {
145-
146-
BeanDefinition indexDefinition = BeanDefinitionBuilder
147-
.genericBeanDefinition(configuration.getRequiredAttribute("indexConfiguration", Class.class)) //
148-
.getBeanDefinition();
149-
150-
BeanDefinition keyspaceDefinition = BeanDefinitionBuilder
151-
.genericBeanDefinition(configuration.getRequiredAttribute("keyspaceConfiguration", Class.class)) //
152-
.getBeanDefinition();
165+
private static AbstractBeanDefinition createMappingConfigBeanDef(String indexConfigRef, String keyspaceConfigRef) {
153166

154167
return BeanDefinitionBuilder.genericBeanDefinition(MappingConfiguration.class) //
155-
.addConstructorArgValue(indexDefinition) //
156-
.addConstructorArgValue(keyspaceDefinition) //
168+
.addConstructorArgReference(indexConfigRef) //
169+
.addConstructorArgReference(keyspaceConfigRef) //
157170
.getBeanDefinition();
158171
}
159172

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.aot.hint.RuntimeHintsRegistrar=\
2+
org.springframework.data.redis.aot.DataRedisRuntimeHints

0 commit comments

Comments
 (0)