I've been reading about Spring and although it's claimed to be a less complex alternative to EJB, I'm having a hard time wrapping my head around it. Is there a more minimal way of achieving Dependency Injection than adopting the Spring approach?
Why not just do it without a framework ?
Ask what your class depends on, and then inject those objects via (say) the constructor.
Some hints:
- does your class rely on a singleton ? Inject that object instead (probably as a factory)
- does your object rely on other concrete classes ? If so, inject those, but reference them via interfaces, so you an substitute different implementations
e.g. simply create a class with a constructor thus:
public TradeSaver(final ITradeValidator validator, final ITradeDatabase db);
(where both parameters are interfaces) and you can then inject the core components that your TradeSaver
depends on (validation and database saving), with the option of providing different implementations for testing, different deployments etc.
Another option that hasn't been mentionned yet is Yan. I've used it in the past and it was very lightweight and minimalist. Here's a link with a one page introduction as to what (and how) it does:
As far as DI and IoC goes, it probably doesn't get any more minimal than picocontainer.
I prefer Tapestry, but Google Guice is pretty similar and more widely adopted, so that might be a better choice since it will be easier to find tutorials etc.
I highly recommend that you just try Spring. It is a bit more complicated than Guice in the initial stages, however, the wrappers for other APIs and included utilities (LDAPTemplate, JDBCTemplate, HibernateTemplate, Validators, etc) are well worth the cost of admission.
Having said that, if you are dead-set against trying Spring, Guice or Seam offer nice alternatives.
In essence, dependency injection is just a way of structuring your code for reusability of components. It doesn't require the use of a container. It just means that you move any use of the "new" operator for your components to the start of your applicaiton. For example, your application entry point could look like this:
IZooDataRepository repository = new SqlZooDataRepository(somehost, someparam);
IMonkeyManager monkeyManager = new MonkeyManager(repository);
IZebraManager zebraManager = new ZebraManager(repository);
ZooProgram program = new ZooProgram(monkeyManager, zebraManager);
program.run();
This phase is known as the "object graph construction". It is where you wire objects which only know their collaborators as interfaces to specific implementations of those interfaces.
This start-up wiring can get quite long and complicated if you have hundreds of classes in practice. That's why DI containers were invented: they replace the object graph construction code in some way, e.g. like this:
Container container = new Container(someconfigurationparameters);
ZooProgram program = (ZooProgram) container.Create(ZooProgram.class);
program.run();
The configuration of the object graph produced by a container is typically done through XML files, attributes on classes, or bindings defined with code.
PicoContainer is the easiest way to get a started with DI:
suppose we got
public class A implements IA {
public A(IB dependency){
...
}
}
public class B implements IB {
}
then
pico = new DefaultPicoContainer();
pico.addComponent(A.class);
pico.addComponent(B.class);
IA a = pico.getComponent(IA.class); // a is an instance of A with an instance of B passed to the constructor
I would strongly recommend you look into a JSR-330 implementation, as these hopefully should be the future standard. There is one in JEE6 but that may be overkill for you. I believe the Caucho CanDI can run in stand-alone too.