Binding transformations
In this tutorial we will transform bindings declared in a separate standalone module. We will intercept a dependency exported in another module and transform it so that it adds some basic logging before executing the method and after the method finishes.
Example Launcher
First, we will create a new Launcher by extending a Launcher
class.
public class BindingTransformationExample extends Launcher { ...}
Then let's define a Person
interface with a single method void greet()
.
public interface Person { void greet();}
And inject an instance of a Person
class into the application launcher by adding a person
field annotated with @Inject
annotation.
@InjectPerson person;
Our application launcher overrides Launcher#run
method just to call person.greet()
method.
@Overrideprotected void run() { person.greet();}
Person module
An application launcher would use 2 modules to inject a Person person
dependency.
@Overrideprotected Module getModule() { return Modules.combine( new PersonModule(), new PersonTransformModule() );}
The first one (PersonModule
) is a simple AbstractModule
that provides a single dependency for a Person
class.
public static class PersonModule extends AbstractModule { @Provides Person greeter() { return () -> System.out.println("Hello!"); }}
A provided Person
simply prints "Hello!"
when greet()
method is called.
Person transformation module
A PersonTransformModule
is a module that would intercept a provided Person
class and add logging to greet()
method calls.
public static class PersonTransformModule extends AbstractModule { @Override protected void configure() { transform(Person.class, (bindings, scope, key, binding) -> binding.mapInstance(person -> () -> { System.out.println("Start of greeting"); person.greet(); System.out.println("End of greeting"); } )); }}
The module does not export any dependency using @Provides
annotation. Instead it overrides AbstractModule#configure
method just to call transform(...)
method.
Let's take a closer look at transform(...)
call. It takes 2 arguments:
Class
- a class of a binding which will be transformed (this can be changed to aKeyPattern
to transform all bindings matched by a key pattern.BindingTransformer<T>
- a transformer which is itself a functional interfaces that takes bindings, scope, current key and binding and returns a new binding (or the same binding if no transformation happened)
We call Binding#mapInstance
method on a a received binding and specify how an instance of a Person
should be transformed.
Here, we return a new instance of Person
class that adds some System.out
logging before and after calling person.greet()
on an original person instance.
Launching the example
To launch the example we need to define the main
method which would simply create a new instance of our application launcher and pass application arguments to Launcher#launch
method.
public static void main(String[] args) throws Exception { BindingTransformationExample launcher = new BindingTransformationExample(); launcher.launch(args);}
When launching the application it should print to stdout
:
Start of greetingHello!End of greeting
You can find example sources on Github