All Downloads are FREE. Search and download functionalities are using the official Maven repository.

play.api.inject.Injector.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2009-2016 Lightbend Inc. 
 */
package play.api.inject

import scala.reflect.ClassTag

/**
 * An injector, capable of providing components.
 *
 * This is an abstraction over whatever dependency injection is being used in Play. A minimal implementation may only
 * call `newInstance` on the passed in class.
 *
 * This abstraction is primarily provided for libraries that want to remain agnostic to the type of dependency
 * injection being used. End users are encouraged to use the facilities provided by the dependency injection framework
 * they are using directly, for example, if using Guice, use [[http://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/Injector.html com.google.inject.Injector]]
 * instead of this.
 *
 */
trait Injector {

  /**
   * Get an instance of the given class from the injector.
   */
  def instanceOf[T: ClassTag]: T

  /**
   * Get an instance of the given class from the injector.
   */
  def instanceOf[T](clazz: Class[T]): T

  /**
   * Get an instance bound to the given binding key.
   */
  def instanceOf[T](key: BindingKey[T]): T
}

/**
 * An injector that simply creates a new instance of the passed in classes using the classes no-arg constructor.
 */
object NewInstanceInjector extends Injector {

  /**
   * Get an instance of the given class from the injector.
   */
  def instanceOf[T](implicit ct: ClassTag[T]) = instanceOf(ct.runtimeClass.asInstanceOf[Class[T]])

  /**
   * Get an instance of the given class from the injector.
   */
  def instanceOf[T](clazz: Class[T]) = clazz.newInstance()

  /**
   * Get an instance bound to the given binding key.
   */
  def instanceOf[T](key: BindingKey[T]) = instanceOf(key.clazz)
}

/**
 * A simple map backed injector.
 *
 * This injector is intended for use by compile time injected applications in the transitional period between when Play
 * fully supports dependency injection across the whole code base, and when some parts of Play still access core
 * components through Play's global state. Since Play's global state requires that some components are still dynamically
 * looked up from an injector, when using a compile time DI approach, there is typically no way to dynamically look up
 * components, so this provides a simple implementation of the [[Injector]] trait to allow components
 * that Play requires to be dynamically looked up.
 *
 * It is intended to just hold built in Play components, but may be used to add additional components by end users when
 * required.
 *
 * The injector is an immutable structure, new components can be added using the `+` convenience method, which returns
 * a new injector with that component included.
 *
 * @param fallback The injector to fallback to if no component can be found.
 * @param components The components that this injector provides.
 */
class SimpleInjector(fallback: Injector, components: Map[Class[_], Any] = Map.empty) extends Injector {
  /**
   * Get an instance of the given class from the injector.
   */
  def instanceOf[T](implicit ct: ClassTag[T]) = instanceOf(ct.runtimeClass.asInstanceOf[Class[T]])

  /**
   * Get an instance of the given class from the injector.
   */
  def instanceOf[T](clazz: Class[T]) = components.getOrElse(clazz, fallback.instanceOf(clazz)).asInstanceOf[T]

  /**
   * Get an instance bound to the given binding key.
   */
  def instanceOf[T](key: BindingKey[T]) = instanceOf(key.clazz)

  /**
   * Add a component to the injector.
   */
  def +[T](component: T)(implicit ct: ClassTag[T]) =
    new SimpleInjector(fallback, components + (ct.runtimeClass -> component))
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy