toothpick-runtime / toothpick

Package toothpick

Types

InjectorImpl

open class InjectorImpl : Injector

Default implementation of an injector.

InternalProvider

open class InternalProvider<T : Any>

A non thread safe internal provider. It should never be exposed outside of Toothpick.

InternalScopedProvider

open class InternalScopedProvider<T : Any> : InternalProvider<T>

A non thread safe internal provider. It should never be exposed outside of Toothpick.

ScopeImpl

open class ScopeImpl : ScopeNode

{@inheritDoc}

A note on concurrency :

  • all operations related to the scope tree are synchronized on the Toothpick class.
  • all operations related to a scope's content (binding & providers) are synchronized on the key (class) of the binding/injection.
  • all providers provided by the public API (including Lazy) should return a thread safe provider (done) but internally, we can live with a non synchronized provider.
All operations on the scope itself are non thread-safe. They must be used via the Toothpick class or must be synchronized using the Toothpick class if used concurrently.

ScopeNode

abstract class ScopeNode : Scope

A scope is one of the most important concept in Toothpick. It is actually important in Dependency Injection at large and Toothpick exposes it to developers.

Conceptually a scope contains toothpick.config.Bindings & scoped instances :

binding is way to express that a class Foo is bound to an implementation Bar. It means that writing @Inject Foo a; will return a Bar. Bindings are valid for the scope where there are defined, and inherited by children scopes. Children scopes can override any binding inherited from of a parent. Modules allow to define s and are installed in scopes. scoped instance a scoped instance is an instance that is reused for all injection of a given class. Not all bindings create scoped instances. Bindings Foo to an instance or to a instance means that those instances will be recycled every time we inject Foo from this scope. Scoped instances are all lazily initialized on first injection request.

In toothpick, Scopes create a tree (actually a disjoint forest). Each scope can have children scopes. Operations on the scope tree (adding / removing children, etc.) are non thread safe. The implementation of Toothpick provides a Toothpick class that wraps these operations in a thread safe way.

Scopes can be support scope annotations: annotation classes qualified by the annotation. All classes annotated by this annotation will automatically be scoped by Toothpick in the scope that supports them.

Classes that are not annotated with a javax.inject.Scope annotation, also called un-scoped classes, are not associated to a particular scope and can be used in all scopes. Their instances are not recycled, every injection provides a different instance. Scoping a class by annotation is conceptually exactly the same as binding it to itself in a scope.

Scope resolution : when a class is scoped, either by binding it in a module and then installing this module in a scope, or by adding a javax.inject.Scope annotation, it means that all its dependencies must be found in the scope itself or a parent scope. Otherwise, Toothpick will crash at runtime when first instantiating this class. The only other allowed alternative is to have an un-scoped dependency.

ThreadSafeProviderImpl

open class ThreadSafeProviderImpl<T : Any> : Provider<T>, Lazy<T>

A thread safe internal provider. It will be exposed outside of Toothpick.

Toothpick

open class Toothpick

Main class to access toothpick features. It allows to create / retrieve scopes and perform injections.

The main rule about using TP is : TP will honor all injections in the instances it creates by itself. A soon as you use new Foo, in a provider or a binding for instance, TP is not responsible for injecting Foo; developers have to manually inject the instances they create.