docs: public static <T> Provider<T> of(final Class<? extends T> type) {
          return new ProviderWithExtensionVisitor<T>() {
              private volatile T instance;
              private Injector injector;
              private Set<LifecycleListener> listeners = Collections.emptySet();
              
              public T get() {
                  if ( instance == null ) {
                      synchronized (this) {
                          if ( instance == null ) {
                              instance = createAndInjectMember();
                          }
                      }
                  }
                  return instance;
              }
              
              private T createAndInjectMember() {
                  T instance = create();
                  injector.injectMembers(instance);
                  return instance;
              }
              
              private T create() {
                  // Look for an @Inject constructor or just create a new instance if not found
                  InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(type);
                  final long startTime = System.nanoTime();
                  
                  for (LifecycleListener listener : listeners) {
                      listener.objectInjecting(TypeLiteral.get(type));
                  }
                  if (injectionPoint != null) {
                      List<Dependency<?>> deps = injectionPoint.getDependencies();
                      if (deps.size() > 0) {
                          Constructor<?> constructor = (Constructor<?>)injectionPoint.getMember();
                          // One thread for each dependency
                          ExecutorService executor = Executors.newCachedThreadPool(
                                  new ThreadFactoryBuilder()
                                      .setDaemon(true)
                                      .setNameFormat("ConcurrentProviders-" + type.getSimpleName() + "-%d")
                                      .build());
                          try {
                              List<Supplier<?>> suppliers = Lists.newArrayListWithCapacity(deps.size());
                              
                              // Iterate all constructor dependencies and get and instance from the Injector
                              for (final Dependency<?> dep : deps) {
                                  if (!isConcurrent(constructor, dep.getParameterIndex())) {
                                      suppliers.add(getCreator(dep.getKey()));
                                  }
                                  else {
                                      final Future<?> future = executor.submit(new Callable<Object>() {
                                          @Override
                                          public Object call() throws Exception {
                                              return getCreator(dep.getKey()).get();
                                          }
                                      });
                                      suppliers.add(new Supplier() {
                                          @Override
                                          public Object get() {
                                              try {
                                                  return future.get();
                                              } catch (InterruptedException e) {
                                                  Thread.currentThread().interrupt();
                                                  throw new ProvisionException("interrupted during provision");
                                              } catch (ExecutionException e) {
                                                  throw new RuntimeException(e.getCause());
                                              }
                                          }
                                      });
                                  }
                              }
                              // All dependencies are now being instantiated in parallel
                              
                              // Fetch the arguments from the futures and put in an array to pass to newInstance
                              List<Object> params = Lists.newArrayListWithCapacity(deps.size());
                              for (Supplier<?> supplier: suppliers) {
                                  params.add(supplier.get());
                              }
                              
                              // All dependencies have been initialized
                              
                              // Look for the @Inject constructor and invoke it.
                              try {
                                  T obj = (T)constructor.newInstance(params.toArray());
                                  long duration = System.nanoTime() - startTime;
                                  for (LifecycleListener listener : listeners) {
                                      listener.objectInjected((TypeLiteral<T>)TypeLiteral.get(type), obj, duration, TimeUnit.NANOSECONDS);
                                  }
                                  return obj;
                              } catch (Exception e) {
                                  throw new RuntimeException(e);
                              }
                          } 
                          finally {
                              executor.shutdown();
                          }
                      }
                  }
                  
                  try {
                      T obj = type.newInstance();
                      long duration = System.nanoTime() - startTime;
                      for (LifecycleListener listener : listeners) {
                          listener.objectInjected((TypeLiteral<T>)TypeLiteral.get(type), obj, duration, TimeUnit.NANOSECONDS);
                      }
                      return obj;
                  } catch (Exception e) {
                      e.printStackTrace();
                      throw new ProvisionException("Error constructing object of type " + type.getName(), e);
                  }
              }
              
              private boolean isConcurrent(Constructor<?> constructor, int parameterIndex) {
                  Annotation[] annots = constructor.getParameterAnnotations()[parameterIndex];
                  if (annots != null) {
                      for (Annotation annot : annots) {
                          if (annot.annotationType().equals(NonConcurrent.class)) {
                              return false;
                          }
                      }
                  }
                  return true;
              }
  
              /**
               * Required to get the Injector in {@link initialize()}
               */
              @Override
              public <B, V> V acceptExtensionVisitor(
                      BindingTargetVisitor<B, V> visitor,
                      ProviderInstanceBinding<? extends B> binding) {
                  return visitor.visit(binding);
              }
              
              @Inject
              @Toolable
              void initialize(Injector injector) {
                  this.injector = injector;
              }
              
              @Inject(optional = true) 
              void setListeners(Set<LifecycleListener> listeners) {
                  this.listeners = listeners;
              }
              
              public <S> Supplier<S> getCreator(final Key<S> key) {
                  return new Supplier<S>() {
                      @Override
                      public S get() {
                          final long startTime = System.nanoTime();
                          for (LifecycleListener listener : listeners) {
                              listener.objectInjecting(key.getTypeLiteral());
                          }
                          S obj = injector.getInstance(key);
                          final long duration = System.nanoTime() - startTime;
                          for (LifecycleListener listener : listeners) {
                              listener.objectInjected(key.getTypeLiteral(), obj, duration, TimeUnit.NANOSECONDS);
                          }
                          return obj;
                      }
                  };
              }
  
          };
      }