Over a million developers have joined DZone.
Platinum Partner

Qi4j: Fixing Dependency Injection

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

There was a blog post about how "Dependency Injection is Broken". The issues pointed out in the post are dealt with in Qi4j, and I'd like to briefly outline how it works.

First issue:

The problem I've always had with DI frameworks, be it Spring or Guice, is they create this nasty dependency tree. If you don't want to use GlobalApplicationContext.getBean() or Injector.getInstance() then you'll need to inject all your dependencies at the root. It annoys the crap out of me, but I suppose there's just no way around it...

This is dealt with in Qi4j by allowing objects to be instantiated without having direct access to all the dependencies needed by the object. If you have a class Foo that requires a Bar service, like this:

public class Foo
@Service Bar bar;

then you can instantiate it wherever you want by simply doing:
Foo foo = objectBuilderFactory.newObject(Foo.class);
which will instantiate Foo and provide all the dependencies it needs, without the caller having to provide them explicitly.

It is also possible to use service locators in Qi4j, like this:

public class Foo
@Structure ServiceFinder finder;
public void doStuff()
ServiceReference<Bar> barRef = finder.findService(Bar.class);
Bar bar = barRef.get();

Another issue pointed out is the ability to say "realize an object of type X, but I don't know what concrete type it should be". This is so that application code only has to be aware of the base class or interface X, which in runtime can be bound to XImpl or XMock or some other implementation. This is supported in Qi4j since all classes that are to be instantiated must be registered upfront. You can therefore register an implementation like this in the Assembler:

public void assemble(ModuleAssembly module)
module.addObjects(XImpl.class); // XImpl implements X interface

and instantiate it with:
X x = objectBuilderFactory.newObject(X.class);
Based on what you registered the appropriate implementation will be chosen. In the above case XImpl will be instantiated, and if you instead registered XMock which also implements X, then that would be instantiated. If many possibilities exist, an AmbiguousTypeException will be thrown to avoid non-deterministic behaviour.

That should take care of most of the issues pointed out in the post I think. Also note that all of the above mechanism considers visibility rules of the Layers and Modules in the Application, which can be used to further control what types are "seen" by application code in various parts of your app.

From: http://www.jroller.com/rickard/

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}