The EZinjector interface consists only of the @Dependency annotation. To use EZinjector simply use the annotation where you want objects injected. No configuration files are needed and no need to specify any bindings.
Inject an instance of Cache into the cache field:
public class CacheReader {
@Dependency
private Cache cache;
public Cache getCache() {
return this.cache;
}
...
}
or
public class CacheReader {
private Cache cache;
@Dependency
public Cache getCache() {
return this.cache;
}
...
}
In both examples the the cache field is injected with an instance of Cache.
Inject an instance of Cache into the cache field, but only look for implementations in the org.opencache package:
public class CacheReader {
@Dependency(restriction="org.opencache")
private Cache cache;
public Cache getCache() {
return this.cache;
}
...
}
or
public class CacheReader {
private Cache cache;
@Dependency(restriction="org.opencache")
public Cache getCache() {
return this.cache;
}
...
}
Inject an instance of Cache into the cache field, but treat it as a singleton. If the Cache class manages itself as a singleton (perhaps with a getInstance() method), then the instance it provides is used; otherwise a new instance is created and stored. This stored instance will be used for all subsequent injections providing singleton-like behavior.
public class CacheReader {
@Dependency(singleton=true)
private Cache cache;
public Cache getCache() {
return this.cache;
}
...
}
or
public class CacheReader {
private Cache cache;
@Dependency(singleton=true)
public Cache getCache() {
return this.cache;
}
...
}
The @Dependency annotation has two attributes that affect how the injected instance is treated: restriction and singleton.
restriction (default value is empty string):
The restriction attribute indicates that only an instance from the specified package should be injected. For example, if the Apache Commons-Collections package were specified:
@Dependency(restriction="org.apache.commons.collections") private Collection myCollection;
then an instance of one of the Apache collections would be injected.
singleton (default value is false):
The singleton attribute indicates that the instance injected should be treated as a singleton. This flag indicates either the implementation manages itself as a singleton or that EZinjector should manage it as a singleton.
When the @Dependency annotation is applied to a field (non-final & non-static) EZinjector will inject an appropriate implementation. For example:
public class ActiveMQueue implements MessageQueue {
public void send(Message m) {
...
}
...
}
public class Client {
@Dependency
private MessageQueue mQueue;
...
}
The first time mQueue is referenced an implementation of MessageQueue will be injected, specifically an instance of ActiveMQueue. Subsequent usage of mQueue will behave as if it were explicitly set to an instance of ActiveMQueue.
public class ActiveMQueue implements MessageQueue {
public void sent(Message m) {
...
}
...
}
public class Client {
private MessageQueue mQueue;
@Dependency
public MessageQueue getMQueue() {
return mQueue;
}
...
}
The first time getMQueue() is called the field mQueue will be injected with an instance of ActiveMQueue. Any subsequent use of getMQueue() or mQueue will behave as if the field were set explicitly. If, however, the Client class did not have the mQueue field:
public class Client {
@Dependency
public MessageQueue getMQueue() {
return null;
}
...
}
Then each time the getMQueue() method is called a new instance of ActiveMQueue will be injected. In the following example q1 and q2 refer to different instances of ActiveMQueue:
Client client = new Client(); MessageQueue q1 = client.getMQueue(); MessageQueue q2 = client.getMQueue(); q1 != q2; // evaluates to true
Generics may be used when specifying the interface for a dependency. For example, the following classes
public interface Reader<T extends InputStream> {
public byte[] read(T inputStream);
}
public class FileReader implements Reader<FileInputStream> {
public byte[] read(FileInputStream inputStream) {
...
}
}
could be used as follows:
public class Application {
@Dependency
Reader<FileInputStream> reader;
...
}
or
public class Application {
private Reader<FileInputStream> reader;
@Dependency
public Reader<FileInputStream> getReader() {
return reader;
}
...
}
In each case an instance of FileReader would be injected into the reader field.
EZinjector relies on AspectJ for weaving, so setup is as simple as enabling AspectJ's Load-Time Weaving. This is done by running your application with the -javaagent JVM arg pointing to the AspectJ Weaver JAR:
$> java -javaagent:pathto/aspectjweaver.jar -cp ... MyApp