Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Spring dependency injection have init-method?

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' ?

like image 997
dreadwail Avatar asked Dec 09 '22 23:12

dreadwail


2 Answers

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.

like image 104
Tomasz Nurkiewicz Avatar answered Dec 31 '22 10:12

Tomasz Nurkiewicz


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.

like image 32
Stephen C Avatar answered Dec 31 '22 08:12

Stephen C