Skip to content

Commit daecc25

Browse files
authored
perf: optimize SpringLookup lookup time by caching (#17604)
* perf: optimize RouteUtil.resolve method Cache RoutePathProvider in VaadinContext for faster lookup time in RouteUtil.resolve method. * perf: optimize SpringLookup lookup time by caching Cache RoutePathProvider in SpringLookup for faster lookup time especially for RouteUtil#resolve method, but also for all default (and subclasses of default) implementations of services defined in LookupInitializer.getDefaultImplementations().
1 parent 19f21ea commit daecc25

File tree

1 file changed

+40
-4
lines changed

1 file changed

+40
-4
lines changed

vaadin-spring/src/main/java/com/vaadin/flow/spring/SpringLookupInitializer.java

+40-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.util.ArrayList;
2222
import java.util.Collection;
23+
import java.util.HashMap;
2324
import java.util.Map;
2425
import java.util.function.BiFunction;
2526
import java.util.stream.Collectors;
@@ -61,15 +62,44 @@ private static class SpringLookup extends LookupImpl {
6162

6263
private final WebApplicationContext context;
6364

65+
private final Map<Class<?>, Object> cachedServices;
66+
67+
private final Map<Class<?>, Boolean> cacheableServices;
68+
6469
private SpringLookup(WebApplicationContext context,
6570
BiFunction<Class<?>, Class<?>, Object> factory,
6671
Map<Class<?>, Collection<Class<?>>> services) {
6772
super(services, factory);
6873
this.context = context;
74+
this.cachedServices = new HashMap<>();
75+
this.cacheableServices = new HashMap<>();
76+
}
77+
78+
private <T> boolean isCacheableService(Class<T> serviceClass) {
79+
return cacheableServices.computeIfAbsent(serviceClass,
80+
key -> LookupInitializer.getDefaultImplementations()
81+
.stream().anyMatch(serviceClass::isAssignableFrom));
82+
}
83+
84+
private <T> T getCachedService(Class<T> serviceClass) {
85+
return serviceClass.cast(cachedServices.get(serviceClass));
86+
}
87+
88+
private <T> void setCachedService(Class<T> serviceClass, T service) {
89+
cachedServices.put(serviceClass, service);
6990
}
7091

7192
@Override
7293
public <T> T lookup(Class<T> serviceClass) {
94+
boolean cacheableService = isCacheableService(serviceClass);
95+
96+
if (cacheableService) {
97+
T cached = getCachedService(serviceClass);
98+
if (cached != null) {
99+
return cached;
100+
}
101+
}
102+
73103
Collection<T> beans = context.getBeansOfType(serviceClass).values();
74104

75105
// Check whether we have service objects instantiated without Spring
@@ -87,13 +117,19 @@ public <T> T lookup(Class<T> serviceClass) {
87117
allFound.addAll(beans);
88118
allFound.add(service);
89119
}
120+
T lookupResult;
90121
if (allFound.size() == 0) {
91-
return null;
122+
lookupResult = null;
92123
} else if (allFound.size() == 1) {
93-
return allFound.iterator().next();
124+
lookupResult = allFound.iterator().next();
125+
} else {
126+
throw new IllegalStateException(SEVERAL_IMPLS + serviceClass
127+
+ SPI + allFound + ONE_IMPL_REQUIRED);
128+
}
129+
if (cacheableService) {
130+
setCachedService(serviceClass, lookupResult);
94131
}
95-
throw new IllegalStateException(SEVERAL_IMPLS + serviceClass + SPI
96-
+ allFound + ONE_IMPL_REQUIRED);
132+
return lookupResult;
97133
}
98134

99135
@Override

0 commit comments

Comments
 (0)