The part you are missing with inversion-of-control is that the application layer does not call the constructor directly.. It uses a factory (the IoC container) to populate the constructor parameter.
Whatever tool you use, guice / spring / picocontainer / singleton-factories, your application code should look something like:
@Controller
class MyController {
@Resource // Some container knows about this annotation and wires you in
MyBusinessLogic myBusinessLogic;
@RequestMethod("/foo/bar.*")
public MyWebResponse doService(Response resp, long id, String val) {
boolean worked = myBusinessLogic.manipulatevalue(id, val);
return new MyWebResponse(worked);
}
}
Note, the myBusinessLogic could be registered in several ways - java's @Resource, MyBusinessLogicFactory.getMyBusinessLogic(), guice.get(MyBusinessLogic.class), etc.
A poor-mans solution would be:
package foo;
class MyBusinessLogicFactory {
static volatile MyBusinessLogic instance; // package-scoped so unit tests can override
public static MyBusinessLogic getInstance() {
if (instance == null) {
synchronized(MyBusinessLogicFactory.class) {
instance = new MyBusinessLogic(MyDatabaseLayerFactory.getInstance());
}
}
return instance;
}
}
// repeat with MyDatabaseLayerFactory
Note the above singleton model is highly discouraged, since it has no scope. You COULD wrap the above inside a context - soething like
class Context {
Map<Class,Object> class2Instance = new ConcurrentHashMap<>();
public <T> T getInstance(Class<T> clazz) {
Object o = class2Instance.get(clazz);
if (o == null) {
synchronized(this) {
o = class2Instance.get(clazz);
if (o != null) return (T)o;
o = transitivelyLoadInstance(clazz); // details not shown
for (Class c : loadClassTree(clazz)) { // details not shown
class2Instance.put(c, o);
}
}
}
return (T)o;
}
...
}
But at that point, picocontainer, guice and spring can solve the complexities of the above SOOO much better.
Further, things like spring that honor the java 6 annotations mean you can do things other than constructor injection, which is VERY useful if you have multiple configuration items of the same base data-type (e.g. strings).