Пример #1
0
  /** Provisions a new T. */
  private T provision(
      Errors errors, InternalContext context, ConstructionContext<T> constructionContext)
      throws ErrorsException {
    try {
      T t;
      try {
        Object[] parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors);
        t = constructionProxy.newInstance(parameters);
        constructionContext.setProxyDelegates(t);
      } finally {
        constructionContext.finishConstruction();
      }

      // Store reference. If an injector re-enters this factory, they'll get the same reference.
      constructionContext.setCurrentReference(t);

      MembersInjectorImpl<T> localMembersInjector = membersInjector;
      localMembersInjector.injectMembers(t, errors, context, false);
      localMembersInjector.notifyListeners(t, errors);

      return t;
    } catch (InvocationTargetException userException) {
      Throwable cause = userException.getCause() != null ? userException.getCause() : userException;
      throw errors
          .withSource(constructionProxy.getInjectionPoint())
          .errorInjectingConstructor(cause)
          .toException();
    } finally {
      constructionContext.removeCurrentReference();
    }
  }
Пример #2
0
  /**
   * Construct an instance. Returns {@code Object} instead of {@code T} because it may return a
   * proxy.
   */
  Object construct(
      final Errors errors,
      final InternalContext context,
      Dependency<?> dependency,
      /* @Nullable */ ProvisionListenerStackCallback<T> provisionCallback)
      throws ErrorsException {
    final ConstructionContext<T> constructionContext = context.getConstructionContext(this);
    // We have a circular reference between constructors. Return a proxy.
    if (constructionContext.isConstructing()) {
      // TODO (crazybob): if we can't proxy this object, can we proxy the other object?
      return constructionContext.createProxy(
          errors, context.getInjectorOptions(), dependency.getKey().getTypeLiteral().getRawType());
    }

    // If we're re-entering this factory while injecting fields or methods,
    // return the same instance. This prevents infinite loops.
    T t = constructionContext.getCurrentReference();
    if (t != null) {
      if (context.getInjectorOptions().disableCircularProxies) {
        throw errors
            .circularDependenciesDisabled(dependency.getKey().getTypeLiteral().getRawType())
            .toException();
      } else {
        return t;
      }
    }

    constructionContext.startConstruction();
    try {
      // Optimization: Don't go through the callback stack if we have no listeners.
      if (provisionCallback == null) {
        return provision(errors, context, constructionContext);
      } else {
        return provisionCallback.provision(
            errors,
            context,
            new ProvisionCallback<T>() {
              @Override
              public T call() throws ErrorsException {
                return provision(errors, context, constructionContext);
              }
            });
      }
    } finally {
      constructionContext.finishConstruction();
    }
  }
Пример #3
0
  /**
   * Construct an instance. Returns {@code Object} instead of {@code T} because it may return a
   * proxy.
   */
  Object construct(
      final Errors errors,
      final InternalContext context,
      Class<?> expectedType,
      boolean allowProxy,
      ProvisionListenerStackCallback<T> provisionCallback)
      throws ErrorsException {
    final ConstructionContext<T> constructionContext = context.getConstructionContext(this);

    // We have a circular reference between constructors. Return a proxy.
    if (constructionContext.isConstructing()) {
      if (!allowProxy) {
        throw errors.circularProxiesDisabled(expectedType).toException();
      } else {
        // TODO (crazybob): if we can't proxy this object, can we proxy the other object?
        return constructionContext.createProxy(errors, expectedType);
      }
    }

    // If we're re-entering this factory while injecting fields or methods,
    // return the same instance. This prevents infinite loops.
    T t = constructionContext.getCurrentReference();
    if (t != null) {
      return t;
    }

    constructionContext.startConstruction();
    try {
      // Optimization: Don't go through the callback stack if we have no listeners.
      if (!provisionCallback.hasListeners()) {
        return provision(errors, context, constructionContext);
      } else {
        return provisionCallback.provision(
            errors,
            context,
            new ProvisionCallback<T>() {
              public T call() throws ErrorsException {
                return provision(errors, context, constructionContext);
              }
            });
      }
    } finally {
      constructionContext.finishConstruction();
    }
  }