Skip to main content

Scopes

A Scope in ActiveJ Inject allows you to reuse instances. A scoped instances are independent of instances in other scopes. By default, each instance obtained from an Injector is singleton. That means it is cached and when you try to retrieve an instance of the same type once again, a cached instance is returned. But, there are situations when you need to recreate some instances as they are tied to some semantic scope (application scope, request scope, process scope).

For example, we can have a dedicated HTTP scope. Each request will be bound to the HTTP scope and every instance created within this scope is valid only during a lifetime of an HTTP request (time between receiving an HTTP request and returning an HTTP response).

An Injector may "enter" the scope. That means a new scoped Injector will be created out of the main one. This "scoped" injector will have a link to the parent injector, so in case it cannot obtain some instance from within its own scope it will fall back to the parent injector.

Scopes can be nested. You can have a scope inside another scope and so on. When you try to get an instance from a nested scope injector, what happens is the innermost injector gets queried first. If it cannot return an instance, the next upper scope injector will be queried and so on until we can return an instance.

Defining scopes

A scope is represented using a special scope annotation. A scope annotation is a marker annotation (meaning it has no members or data) that is itself annotated with a special marker annotation @ScopeAnnotation.

Here is how we can have define an annotation for HTTP scope:

@ScopeAnnotation@Target(ElementType.METHOD)@Retention(RUNTIME)public @interface HttpScope {}

We can then define a binding within the HTTP scope using ModuleBuilder DSL:

bind(Integer.class).toInstance(123).in(HttpScope.class)

Another way to define a scoped binding is to use scope annotation with @Provides annotated methods like this:

@Provides@HttpScopeInteger integer() {    return 123;}
note

We have annotated scope annotation with @Retention(RUNTIME) annotation as scopes are processed at the runtime.

@Target(ElementType.METHOD) annotation is present because we use scope annotations on methods.

Entering a scope

To enter a certain scope we use Injector#enterScope(Scope) method that returns a "scoped" injector.

For example, let's enter the HTTP scope defined previously:

Injector scopedInjector = injector.enterScope(Scope.of(HttpScope.class));

Now we can use scopedInjector to retrieve instances from within HTTP scope.

You can find a full example of HTTP scope on Github