I come from a .NET background, using dependency injection containers like Unity, Ninject, Castle Windsor, etc. Recently I have begun to learn to use Spring's dependency injection capabilities for Java.
In learning Spring, I've seen that it's possible to specify on a bean XML configuration the notion of an 'init-method' and 'destroy-method'.
The purpose of specifying an 'init-method' appears to be to do any setup at bean creation time that you might want to do. Here's where I get confused. Why would you need a separate method to perform setup, instead of just using the constructor to perform any setup needed by the object, like normal/good object oriented design would dictate?
In other words, if a dependency is required by a class, shouldn't it be injected in the constructor, which you know has been called, whereas the object could exist in a state without having called it's 'init-method' ?
There are few cases where separate init()
method is needed:
legacy APIs where you just don't have any choice
initialization having some side-effects, e.g. starting a Thread
, connecting to som external resources
This actually has even deeper implications: when using class-based proxies (via cglib) constructor of your base class is called twice (second time for the proxy that inhertis from your class) - init()
method is called only once on final object.
you shouldn't perform virtual calls in constructor (this should actually be forbidden by the compiler...)
sometimes you must use setter/field injection (although I love constructor injection), e.g. when aforementioned class-based proxies are used
using the constructor to perform any setup needed by the object, like normal/good object oriented design would dictate?
This isn't actually the best practice to put all initialization code in constructor. Side-effects in constructor make testing and mocking much harder. Instead focus on creating objects in stable and known state. This way you can e.g. decouple creating an object managing the connection pool and physically connecting to that pool.
BTW destroy()
is a blessing in a language without destructors as it allows you to gratefully close external resources, interrupt threads, etc. Use it often.
Why would you need it?
The init method is called after all of the bean's properties have been set. This is typically needed if the bean needs to do some initialization or validation of properties that can only be done after all the properties have been set. (If you try to do this without an "init" callback, you find that each property setter has to check whether the other setters have been called, and so on. And even that strategy fails if the initialization can only be done after all properties in a cycle of beans have been set.)
The destroy method is needed if the bean holds resources that need to be explicitly released; e.g. file handles, network sockets, database connections.
... like normal/good object oriented design would dictate?
Any design methodology that dictates that init and destroy events / methods are "wrong" or "forbidden" is unrealistic and should be ignored. In fact object oriented design methodologies typically don't dictate this. At most they would say that this kind of thing is not normally needed.
Furthermore, DI actually changes the rules somewhat for the design methodology ... at least with respect to initialization. In particular, by externalizing the "wiring up" of the instances, it pulls much out of the logic out of the code in a way that classical OO design methodologies don't anticipate. If anything, this is saying that classical OO methodologies need to be revisited in the light of Dependency Injection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With