Skip to content

Commit 23473ab

Browse files
authored
Fix "Recursive update' for scoped proxies (micronaut-projects#3824)
1 parent b4044ad commit 23473ab

File tree

2 files changed

+85
-3
lines changed

2 files changed

+85
-3
lines changed

inject/src/main/java/io/micronaut/context/DefaultBeanContext.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public <BT extends BeanType<Object>> Stream<BT> reduce(Class<Object> beanType, S
107107

108108
final Map<BeanKey, BeanRegistration> singletonObjects = new ConcurrentHashMap<>(100);
109109
final Map<BeanIdentifier, Object> singlesInCreation = new ConcurrentHashMap<>(5);
110-
final Map<BeanKey, Object> scopedProxies = new ConcurrentHashMap<>(20);
110+
final Map<BeanKey, Provider<Object>> scopedProxies = new ConcurrentHashMap<>(20);
111111

112112
Set<Map.Entry<Class, List<BeanInitializedEventListener>>> beanInitializedEventListeners;
113113

@@ -2313,7 +2313,7 @@ private <T> T getScopedBeanForDefinition(
23132313
Class<?> proxiedType = resolveProxiedType(beanType, definition);
23142314
BeanKey key = new BeanKey(proxiedType, qualifier);
23152315
BeanDefinition<T> finalDefinition = definition;
2316-
return (T) scopedProxies.computeIfAbsent(key, (Function<BeanKey, T>) beanKey -> {
2316+
return (T) scopedProxies.computeIfAbsent(key, beanKey -> ProviderUtils.memoized(() -> {
23172317
Qualifier<T> q = qualifier;
23182318
if (q == null) {
23192319
q = finalDefinition.getDeclaredQualifier();
@@ -2328,7 +2328,7 @@ private <T> T getScopedBeanForDefinition(
23282328
throw new NoSuchBeanException(proxyDefinition.getBeanType(), qualifier);
23292329
}
23302330
return createBean;
2331-
});
2331+
})).get();
23322332
} else {
23332333
Optional<BeanResolutionContext.Segment<?>> currentSegment = resolutionContext.getPath().currentSegment();
23342334
Optional<CustomScope> registeredScope = Optional.empty();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2017-2020 original 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 io.micronaut.context;
17+
18+
19+
import javax.inject.Provider;
20+
import javax.validation.constraints.NotNull;
21+
22+
/**
23+
* Helper methods for dealing with {@link javax.inject.Provider}.
24+
*
25+
* @author Denis Stepanov
26+
* @since 2.0.2
27+
*/
28+
public class ProviderUtils {
29+
30+
/**
31+
* Caches the result of provider in a thread safe manner.
32+
*
33+
* @param delegate The provider providing the result
34+
* @param <T> The type of result
35+
* @return A new provider that will cache the result
36+
*/
37+
public static <T> Provider<T> memoized(Provider<T> delegate) {
38+
return new MemoizingProvider<>(delegate);
39+
}
40+
41+
/**
42+
* A lazy provider.
43+
*
44+
* @param <T> The type
45+
* @author Denis Stepanov
46+
* @since 2.0.2
47+
*/
48+
private static final class MemoizingProvider<T> implements Provider<T> {
49+
50+
private Provider<T> actual;
51+
private Provider<T> delegate = this::initialize;
52+
private boolean initialized;
53+
54+
MemoizingProvider(@NotNull Provider<T> actual) {
55+
this.actual = actual;
56+
}
57+
58+
@Override
59+
public T get() {
60+
return delegate.get();
61+
}
62+
63+
private synchronized T initialize() {
64+
if (!initialized) {
65+
T value = actual.get();
66+
delegate = () -> value;
67+
initialized = true;
68+
actual = null;
69+
}
70+
return delegate.get();
71+
}
72+
73+
@Override
74+
public String toString() {
75+
if (initialized) {
76+
return "Provider of " + delegate.get();
77+
}
78+
return "ProviderUtils.memoized(" + actual + ")";
79+
}
80+
81+
}
82+
}

0 commit comments

Comments
 (0)