Interface InstanceProvider

Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

Contract for concrete instance generation given type information.

A standard threadsafe implementation can be acquired via the defaultInstance() factory method.

See https://www.soklet.com/docs/instance-creation for detailed documentation.

Author:
Mark Allen
  • Method Summary

    Modifier and Type
    Method
    Description
    Acquires a threadsafe InstanceProvider with a reflection-based instanceClass.getDeclaredConstructor().newInstance() instantiation strategy.
    <T> T
    provide(Class<T> instanceClass)
    Vends an instance of the given class.
    default <T> T
    provide(Parameter parameter)
    Vends an instance appropriate for the supplied Parameter.
  • Method Details

    • provide

      @Nonnull <T> T provide(@Nonnull Class<T> instanceClass)
      Vends an instance of the given class.

      The instance does not necessarily have to be new for every invocation (for example, implementors might return cached instances).

      Type Parameters:
      T - the type of class to instantiate
      Parameters:
      instanceClass - type token which represents the class to instantiate
      Returns:
      an instance of T
    • provide

      @Nonnull default <T> T provide(@Nonnull Parameter parameter)
      Vends an instance appropriate for the supplied Parameter.

      This is useful for solving the "robot legs" problem, where you might examine a qualifying annotation on a parameter to disambiguate vended instances.

      For example, given this Resource Method:

      @GET("/robot-generator")
      public Robot robotGenerator(
        @Left LegFactory leftLegFactory, // Custom annotation
        @Right LegFactory rightLegFactory, // Custom annotation
        BodyFactory bodyFactory
      ) {
        // Build a robot
        LeftLeg leftLeg = leftLegFactory.buildLeg();
        LeftLeg rightLeg = rightLegFactory.buildLeg();
        Body body = bodyFactory.build();
        return new Robot(leftLeg, rightLeg, body);
      }

      Your implementation might look like this:

      @Override
      @SuppressWarnings("unchecked")
      public <T> T provide(@Nonnull Parameter parameter) {
        Class<T> type = (Class<T>) parameter.getType();
      
        // Pick the appropriate LegFactory by inspecting annotations
        if (type == LegFactory.class) {
          if (parameter.isAnnotationPresent(Left.class))
            return (T) LEFT_INSTANCE;
          if (parameter.isAnnotationPresent(Right.class))
            return (T) RIGHT_INSTANCE;
      
          throw new IllegalArgumentException("LegFactory requires @Left or @Right");
        }
      
        // No qualifier logic needed - use the class-based path
        return provide(type);
      }

      The default implementation delegates to provide(Class) using the parameter's raw type.

      Type Parameters:
      T - the type of class to instantiate (by default, the value of Parameter.getType())
      Parameters:
      parameter - the parameter instance to instantiate
      Returns:
      an instance of T
    • defaultInstance

      Acquires a threadsafe InstanceProvider with a reflection-based instanceClass.getDeclaredConstructor().newInstance() instantiation strategy.

      The returned instance is guaranteed to be a JVM-wide singleton.

      Returns:
      an InstanceProvider with a reflection-based instantiation strategy