Skip to content

Commit e4bd5b3

Browse files
Add native hints for Caffeine cache. (#1194)
1 parent 9a06eb4 commit e4bd5b3

File tree

4 files changed

+64
-2
lines changed

4 files changed

+64
-2
lines changed

docs/src/main/asciidoc/spring-cloud-commons.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ public class MyClass {
635635
The Spring WebFlux can work with both reactive and non-reactive `WebClient` configurations, as the topics describe:
636636

637637
* <<webflux-with-reactive-loadbalancer>>
638-
* <<load-balancer-exchange-filter-functionload-balancer-exchange-filter-function>>
638+
* <<load-balancer-exchange-filter-function>>
639639

640640
[[webflux-with-reactive-loadbalancer]]
641641
==== Spring WebFlux `WebClient` with `ReactorLoadBalancerExchangeFilterFunction`

spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfiguration.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,21 @@
1616

1717
package org.springframework.cloud.loadbalancer.config;
1818

19+
import java.util.Objects;
20+
import java.util.Set;
21+
import java.util.stream.Collectors;
22+
1923
import com.github.benmanes.caffeine.cache.Caffeine;
2024
import com.stoyanr.evictor.ConcurrentMapWithTimedEviction;
2125
import org.apache.commons.logging.Log;
2226
import org.apache.commons.logging.LogFactory;
2327

28+
import org.springframework.aot.hint.MemberCategory;
29+
import org.springframework.aot.hint.RuntimeHints;
30+
import org.springframework.aot.hint.RuntimeHintsRegistrar;
31+
import org.springframework.aot.hint.TypeReference;
2432
import org.springframework.beans.factory.InitializingBean;
33+
import org.springframework.beans.factory.config.BeanDefinition;
2534
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2635
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
2736
import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
@@ -39,8 +48,11 @@
3948
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
4049
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheProperties;
4150
import org.springframework.context.annotation.Bean;
51+
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
4252
import org.springframework.context.annotation.Conditional;
4353
import org.springframework.context.annotation.Configuration;
54+
import org.springframework.core.type.filter.AssignableTypeFilter;
55+
import org.springframework.util.ClassUtils;
4456

4557
/**
4658
* An AutoConfiguration that automatically enables caching when Spring Boot, and Spring
@@ -149,3 +161,52 @@ static class LoadBalancerCacheEnabled {
149161
}
150162

151163
}
164+
165+
// Remove after adding hints to GraalVM reachability metadata repo
166+
class CaffeineHints implements RuntimeHintsRegistrar {
167+
168+
private static final Log LOG = LogFactory.getLog(CaffeineHints.class);
169+
170+
private static final String CAFFEINE_BOUNDED_LOCAL_CACHE_CLASS_NAME = "com.github.benmanes.caffeine.cache.BoundedLocalCache";
171+
172+
private static final String CAFFEINE_CACHE_BASE_PACKAGE = "com/github/benmanes/caffeine/cache";
173+
174+
private static final String CAFFEINE_NODE_CLASS_NAME = "com.github.benmanes.caffeine.cache.Node";
175+
176+
@Override
177+
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
178+
if (!ClassUtils.isPresent("com.github.benmanes.caffeine.cache.Caffeine", classLoader)) {
179+
return;
180+
}
181+
hints.reflection()
182+
.registerType(TypeReference.of(Caffeine.class),
183+
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
184+
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
185+
.registerType(TypeReference.of("com.github.benmanes.caffeine.cache.BoundedLocalCache"),
186+
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
187+
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
188+
.registerType(TypeReference.of("com.github.benmanes.caffeine.cache.LocalCacheFactory"),
189+
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
190+
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS))
191+
.registerType(TypeReference.of("com.github.benmanes.caffeine.cache.Node"),
192+
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
193+
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS));
194+
getCaffeineSubtypes().forEach(cacheType -> hints.reflection().registerType(TypeReference.of(cacheType),
195+
hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS,
196+
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.DECLARED_FIELDS)));
197+
}
198+
199+
private Set<String> getCaffeineSubtypes() {
200+
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
201+
try {
202+
provider.addIncludeFilter(new AssignableTypeFilter(Class.forName(CAFFEINE_BOUNDED_LOCAL_CACHE_CLASS_NAME)));
203+
provider.addIncludeFilter(new AssignableTypeFilter(Class.forName(CAFFEINE_NODE_CLASS_NAME)));
204+
}
205+
catch (ClassNotFoundException e) {
206+
LOG.warn("Could not get class for name: " + CAFFEINE_BOUNDED_LOCAL_CACHE_CLASS_NAME);
207+
}
208+
return provider.findCandidateComponents(CAFFEINE_CACHE_BASE_PACKAGE).stream().filter(Objects::nonNull)
209+
.map(BeanDefinition::getBeanClassName).filter(Objects::nonNull).collect(Collectors.toSet());
210+
}
211+
212+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.aot.hint.RuntimeHintsRegistrar=\
2+
org.springframework.cloud.loadbalancer.config.CaffeineHints

spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/config/LoadBalancerCacheAutoConfigurationTests.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
*
3939
* @author Olga Maciaszek-Sharma
4040
*/
41-
4241
class LoadBalancerCacheAutoConfigurationTests {
4342

4443
@Test

0 commit comments

Comments
 (0)