From 40a5bcfab5cfe45c3b6c5ffc9309b310df82775b Mon Sep 17 00:00:00 2001 From: Sam Berlin Date: Mon, 8 May 2023 10:22:17 -0700 Subject: [PATCH] Avoid re-initializing factories that are already initialized. This is necessary because we share the internal factory implementation, which leads to initialize(..) being called multiple times. There are other consequences/quirks of this, but re-initialization is the worst of it. PiperOrigin-RevId: 530339379 --- .../google/inject/internal/RealMapBinder.java | 23 +++++++++++++++++++ .../inject/internal/RealOptionalBinder.java | 12 ++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/core/src/com/google/inject/internal/RealMapBinder.java b/core/src/com/google/inject/internal/RealMapBinder.java index 52c84a09c0..6a743630cf 100644 --- a/core/src/com/google/inject/internal/RealMapBinder.java +++ b/core/src/com/google/inject/internal/RealMapBinder.java @@ -701,6 +701,7 @@ private static final class RealProviderMapProvider extends RealMapBinderProviderWithDependencies>> { private Map> mapOfProviders; private Set> dependencies = RealMapBinder.MODULE_DEPENDENCIES; + private boolean initialized; private RealProviderMapProvider(BindingSelection bindingSelection) { super(bindingSelection); @@ -713,6 +714,10 @@ public Set> getDependencies() { @Override protected void doInitialize(InjectorImpl injector, Errors errors) { + if (initialized) { + return; + } + initialized = true; ImmutableMap.Builder> mapOfProvidersBuilder = ImmutableMap.builder(); ImmutableSet.Builder> dependenciesBuilder = ImmutableSet.builder(); for (Map.Entry> entry : bindingSelection.getMapBindings().entrySet()) { @@ -743,6 +748,8 @@ private static final class RealMapProvider K[] keys; + private boolean initialized = false; + RealMapProvider(BindingSelection bindingSelection) { super(bindingSelection); } @@ -753,6 +760,10 @@ BindingSelection getBindingSelection() { @Override protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException { + if (initialized) { + return; + } + initialized = true; @SuppressWarnings("unchecked") K[] keysArray = (K[]) new Object[bindingSelection.getMapBindings().size()]; keys = keysArray; @@ -1079,6 +1090,7 @@ private static final class RealProviderMultimapProvider extends RealMultimapBinderProviderWithDependencies>>> { private Map>> multimapOfProviders; private Set> dependencies = RealMapBinder.MODULE_DEPENDENCIES; + private boolean initialized; private RealProviderMultimapProvider(Key> mapKey) { super(mapKey); @@ -1091,6 +1103,10 @@ public Set> getDependencies() { @Override protected void doInitialize(InjectorImpl injector, Errors errors) { + if (initialized) { + return; + } + initialized = true; ImmutableMap.Builder>> multimapOfProvidersBuilder = ImmutableMap.builder(); ImmutableSet.Builder> dependenciesBuilder = ImmutableSet.builder(); @@ -1141,6 +1157,8 @@ private PerKeyData(K key, Binding[] bindings, SingleParameterInjector[] in private PerKeyData[] perKeyDatas; + private boolean initialized = false; + private RealMultimapProvider(Key> mapKey) { super(mapKey); } @@ -1152,6 +1170,11 @@ public Set> getDependencies() { @Override protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException { + if (initialized) { + return; + } + initialized = true; + @SuppressWarnings({"unchecked", "rawtypes"}) PerKeyData[] typedPerKeyData = new PerKeyData[bindingSelection.getMapBindings().size()]; diff --git a/core/src/com/google/inject/internal/RealOptionalBinder.java b/core/src/com/google/inject/internal/RealOptionalBinder.java index f46771dc98..f9d0b5b869 100644 --- a/core/src/com/google/inject/internal/RealOptionalBinder.java +++ b/core/src/com/google/inject/internal/RealOptionalBinder.java @@ -706,6 +706,7 @@ public int hashCode() { private abstract static class RealOptionalBinderProviderWithDependencies extends InternalProviderInstanceBindingImpl.Factory

{ protected final BindingSelection bindingSelection; + private boolean initialized = false; RealOptionalBinderProviderWithDependencies(BindingSelection bindingSelection) { // We need delayed initialization so we can detect jit bindings created by other bindings @@ -717,8 +718,15 @@ private abstract static class RealOptionalBinderProviderWithDependencies @Override final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { - bindingSelection.initialize(injector, errors); - doInitialize(); + if (!initialized) { + initialized = true; + // Note that bindingSelection.initialize has its own guard, because multiple Factory impls + // will delegate to the same bindingSelection (intentionally). The selection has some + // initialization, and each factory impl has other initialization that it may additionally + // do. + bindingSelection.initialize(injector, errors); + doInitialize(); + } } /**