Class scanning
In this tutorial we will define @Provides
methods in arbitrary classes that do not implement the Module
interface.
Then we will scan these classes to collect providers to the Injector
.
Classes with @Provides
methods
We will define two classes that contain methods annotated with @Provides
annotation. The first class StaticProviders
will contain only static @Provides
-methods.
The other class MixedProviders
contains both static and instance @Provides
-methods.
public static class StaticProviders {
@Provides
static int port() {
return 1234;
}
@Provides
static String databaseName() {
return "exampleDB";
}
}
The StaticProviders
class provides the database name as well as the database port number.
public static class MixedProviders {
private final String hostname;
public MixedProviders(String hostname) {
this.hostname = hostname;
}
@Provides
InetSocketAddress address(int port) {
return new InetSocketAddress(hostname, port);
}
@Provides
static DataSource dataSource(InetSocketAddress address, String dbName) {
return new DataSource(address, dbName);
}
}
The MixedProviders
class provides the database address and the DataSource
class. The DataSource
class requires a database name as well as a database address.
The class looks as follows:
public static final class DataSource {
private final InetSocketAddress address;
private final String dbName;
@Inject
public DataSource(InetSocketAddress address, String dbName) {
this.address = address;
this.dbName = dbName;
}
public String queryData() {
System.out.printf("Querying %s:%s for data%n", address, dbName);
return "data";
}
}
Creating Injector
To create an Injector
, we need to provide some DI modules. But we only have arbitrary classes with @Provides
-methods.
We can use the ModuleBuilder
class to create a module based on these arbitrary classes.
ModuleBuilder
has several scan()
methods that can be used to scan a class or instance and collect providers. The entire class hierarchy is scanned, so the providers defined in the superclasses
would also be collected by scan()
.
This is how we create an Injector
:
public static void main(String[] args) {
Injector injector = Injector.of(
ModuleBuilder.create()
.scan(StaticProviders.class)
.scan(new MixedProviders("example.com"))
.build()
);
DataSource dataSource = injector.getInstance(DataSource.class);
System.out.println(dataSource.queryData());
}
For the StaticProviders
class, which contains only static providers, we do not need an instance of the class. So we only pass the class to the scan()
method.
Alternatively, the MixedProviders
class also contains a non-static provider method, so we need to pass an instance of MixedProviders
to the scan()
method.
All collected providers form a new Module
which is then passed to the Injcetor
.
You can find example sources on Github