code: private <T> InternalProviderImpl<? extends T> getInternalProvider(Class<T> clazz, String bindingName, boolean isBound) {
      if (bindingName == null) {
        if (isBound) {
          synchronized (mapClassesToUnNamedBoundProviders) {
            return mapClassesToUnNamedBoundProviders.get(clazz);
          }
        } else {
          synchronized (mapClassesToUnNamedUnBoundProviders) {
            return mapClassesToUnNamedUnBoundProviders.get(clazz);
          }
        }
      } else {
        synchronized (mapClassesToNamedBoundProviders) {
          Map<String, InternalProviderImpl> mapNameToProvider = mapClassesToNamedBoundProviders.get(clazz);
          if (mapNameToProvider == null) {
            return null;
          }
          return mapNameToProvider.get(bindingName);
        }
      }
    }
docs: Obtains the provider of the class {@code clazz} and name {@code bindingName}. The returned provider
  can either be bound to the scope or not depending on {@code isBound}.
  Ancestors are not taken into account.
  
  @param clazz the class for which to obtain the provider.
  @param bindingName the name, possibly {@code null}, for which to obtain the provider.
  @param <T> the type of {@code clazz}.
  @return the provider for class {@code clazz} and {@code bindingName},
  either from the set of providers bound to the scope or from the pool of unbound providers.
  If there is no such provider, returns {@code null}.
  
  Note to maintainers : we don't use this method directly, both {@link #getBoundProvider} and {@link #getUnBoundProvider}
  are a facade of this method and make the calls more clear.