Scaffold your ideas into application
Get your free alpha access now.
Only 445 left, Hurry!
24 Oct 2016

Inversion of Control Spring (IOC)

Dont call us, we will call you

I have often asked this question in my interviews that what is the value which Spring framework adds to the application and I have heard answer which are partially correct to outright bizarre.

Most of people talk about Inversion of Control (IOC) but fail to understand the concept of IOC. If we call some thing inversion of control, I would assume that there must be some of the application control which should be inverted. So exactly what control or aspect of application gets inverted while using spring framework.

When using spring, the dependency gets injected into your classes as opposed to you looking for it. This inversion is known as inversion of control. In its simplicity, it seems a very trivial change in architecture to have such a huge impact to start almost a movement which uprooted EJB (Enterprise Java Bean). There is a popular reference to hollywood priciple in regards to how dependency is managed, hollywood principle says which is dont call us, we will call you. In IOC, the dependent does not call the dependency, the container calls the dependency and pushes it in to dependent instance.

Let us analyze dependency management to understand why IOC or DI changes your application paradigm.

In normal application developer would intialize or create a new instance of another class and call a method on it. The initialized class is a "dependency" to the calling class, so essentially any application which has more than 1 class would have dependency. Now this leads to a typical situation where the calling class has to be changed if the dependency changes. To control these changes we need dependency management.

Let us consider a simple example and try to refactor the code for better dependency management.

public class IronMan {
    public IronMan() {
    }

    public void saveTheWorld() {
        Jarvis dependency = new Jarvis();
        dependency.getTheSuit();
    }
}

class Jarvis {
    public Jarvis() {
    }

    public void getTheSuit() {
    }
}

It is often good to regard the dependencies as external libraries which communicate with other parts of application based on standard specification. This can be achieved through creating interfaces for the dependency which serves as the API specification quite like JDBC api or any other java API. Once we have the specification in place we are free to change the implementation as long as the specification stays the same. The most popular example for this would again be JDBC api, as long as the drivers adhere to JDBC specification the calling class or application should not ideally be bothered about whether the underlying implementation is MySQLConnection or OracleConnection. So our code would change to some thing like following.

public class IronMan {
    public IronMan() {
    }

    public void saveTheWorld() {
        SuperHeroHelper dependency = new Jarvis();
        dependency.getTheSuit();
    }
}

interface SuperHeroHelper {
    public void getTheSuit();
}

class Jarvis implements SuperHeroHelper {
    public Jarvis() {
    }

    public void getTheSuit() {
    }
}

The interfaces cleanly seperate the dependencies but we would still need to extract out the part creation part, without which there is not much difference between the above two codes. So lets create a factory class and move the creation logic to factory.

public class IronMan {
    private SuperHeroHelper dependency;

    public IronMan() {
        this.dependency = SuperHeroHelperFactory.getIronManHelper();
    }

    public void saveTheWorld() {
        dependency.getTheSuit();
    }
}

class SuperHeroHelperFactory {
    public static SuperHeroHelper getIronManHelper() {
        SuperHeroHelper dependency = new Jarvis();
        return dependency;
    }
}

interface SuperHeroHelper {
    public void getTheSuit();
}

class Jarvis implements SuperHeroHelper {
    public Jarvis() {
    }

    public void getTheSuit() {
    }
}

At this stage we have a fairly well managed dependency for our Ironman, however if we introduce more superheroes we would need to create one factory per superhero. Lets see how our code changes if we introduce He-Man.

public class IronMan {
    private SuperHeroHelper dependency;

    public IronMan() {
        this.dependency = SuperHeroHelperFactory.getIronManHelper();
    }

    public void saveTheWorld() {
        dependency.getTheSuit();
    }
}

class SuperHeroHelperFactory {
    public static SuperHeroHelper getIronManHelper() {
        SuperHeroHelper dependency = new Jarvis();
        return dependency;
    }

    public static SuperHeroHelper getHeManHelper() {
        SuperHeroHelper dependency = new BattleCat();
        return dependency;
    }
}

interface SuperHeroHelper {
    public void getTheSuit();
}

class Jarvis implements SuperHeroHelper {
    public Jarvis() {
    }

    public void getTheSuit() {
    }
}

class BattleCat implements SuperHeroHelper {
    public void getTheSuit() {
        // No Suit for He-Man
    }
}

class HeMan {
    private SuperHeroHelper dependency;

    public HeMan() {
        this.dependency = SuperHeroHelperFactory.getHeManHelper();
    }

    public void saveTheWorld() {
        dependency.getTheSuit();
    }
}

Now we have to keep changing our factory every time we introduce a new superhero which is not a great design but atleast we are managing the change in a single class, to improve this design further, we could either introduce an abstract factory or a service registry/locator. For the simple reason of scaling to all our superhero, I would choose service locator.

class SuperHeroRegistry {
    private static HashMap helperMap = new HashMap();

    public static void registerHelper(String hero, Class helperClazz) {
        helperMap.put(hero, helperClazz);
    }

    public static SuperHeroHelper getHelper(String hero) {
        Class class1 = (Class) helperMap.get(hero);
        if (class1 != null) {
            try {
                return (SuperHeroHelper) class1.newInstance();
            } catch (Exception e) {
                // Do some exceptional handling. :)
            }
        }
        return null;
    }
}

interface SuperHeroHelper {
    public void getTheSuit();
}

public class IronMan {
    private SuperHeroHelper dependency;

    public IronMan() {
        this.dependency = SuperHeroRegistry.getHelper("IronMan");
    }

    public void saveTheWorld() {
        dependency.getTheSuit();
    }

    public static void main(String[] args) {
        new SuperHeroRegistry();
        new Jarvis();
        new BattleCat();
        new HeMan();
        new IronMan();
    }
}

class Jarvis implements SuperHeroHelper {
    public Jarvis() {
        SuperHeroRegistry.registerHelper("IronMan", Jarvis.class);
    }

    public void getTheSuit() {
    }
}

class BattleCat implements SuperHeroHelper {
    public BattleCat() {
        SuperHeroRegistry.registerHelper("HeMan", BattleCat.class);
    }

    public void getTheSuit() {
        // No Suit for He-Man
    }
}

class HeMan {
    private SuperHeroHelper dependency;

    public HeMan() {
        this.dependency = SuperHeroRegistry.getHelper("HeMan");
    }

    public void saveTheWorld() {
        dependency.getTheSuit();
    }
}

Now we have a rudimentary form or service registry which manages the helpers for all our superhero. This is where we had EJB before Spring came along, all our superheroes were EJB and all our helpers were application resource and we had JNDI which acted as our SuperHeroRegistry. However this setup needed application servers to run and most of the app servers are so heavy weight in terms of memory and CPU which they consume that, they could give the high end gaming systems run for their money. We needed something which is lightweight and efficient and some thing which we could run inside or along with our application.

In 2003,Rod Johnson wrote Spring which brings the container to the application instead of sending application to container. This created a movement which made the app server irrelevant as you could take any web application, add spring framework and you could host it on tomcat or jetty instead of those heavy weight application servers.

Lets try to refactor our code to make a rudimentary form of DI. Essentially we need a class which would initialize all our superhero classes and helper classes and then based on some configuration, inject the appropriate helper in superhero classes.

class MyDIContainer{

    private static Set configSet = new HashSet();

    private static HashMap dependencyMap = new HashMap();

    private HashMap instanceMap = new HashMap();

    public void myCrazyConfiguration(){
        configSet.add(IronMan.class);
        configSet.add(Jarvis.class);
        configSet.add(HeMan.class);
        configSet.add(BattleCat.class);

        //Future expansion
        //configSet.add(Batman.class);
        //configSet.add(Robin.class);

        //dependencyMap.put(SuperHero.class, SuperHeroHelper.class);

        dependencyMap.put(IronMan.class, Jarvis.class);
        dependencyMap.put(HeMan.class, BattleCat.class);

        //Future expansion
        //dependencyMap.put(Batman.class, Robin.class);

    }

    public void doTheMagic(){
        //First Pass, initialize all the classes
        for (Object object : configSet) {
            try {
                Object instance = ((Class)object).newInstance();
                instanceMap.put(instance.getClass(), instance);
            } catch (Exception e) {
                // Do some exceptional handling. :)
            }
        }

        // Second pass, populate dependency

        for (Object object : dependencyMap.keySet()) {

            Class superHeroClazz = (Class) object;
            Class helperClazz = (Class) dependencyMap.get(superHeroClazz);

            Object superHero = instanceMap.get(superHeroClazz);
            Object helper = instanceMap.get(helperClazz);
            try {
                Method method = superHero.getClass().getMethod("setDependency",new Class[]{SuperHeroHelper.class});
                method.invoke(superHero, helper);
            } catch (Exception e) {
                // Do some exceptional handling. :)
            }

        }

    }

    public Object getSuperHero(Class superHeroClazz){
        return instanceMap.get(superHeroClazz);
    }
}

interface SuperHeroHelper {
    public void getTheSuit();
}

public class IronMan {

    private SuperHeroHelper dependency;

    public IronMan() {
    }

    public void saveTheWorld() {
        dependency.getTheSuit();
    }

    public void setDependency(SuperHeroHelper dependency) {
        this.dependency = dependency;
    }

    public static void main(String[] args) {
        MyDIContainer myDIContainer = new MyDIContainer();
        myDIContainer.myCrazyConfiguration();
        myDIContainer.doTheMagic();
        HeMan heMan = (HeMan) myDIContainer.getSuperHero(HeMan.class);
        heMan.saveTheWorld();
    }

}

class Jarvis implements SuperHeroHelper {

    public Jarvis() {
    }

    public void getTheSuit() {

    }
}

class BattleCat implements SuperHeroHelper {

    public BattleCat() {
    }

    public void getTheSuit() {
        // No Suit for He-Man
    }
}

class HeMan {
    private SuperHeroHelper dependency;

    public HeMan() {
    }

    public void saveTheWorld() {
        dependency.getTheSuit();
    }

    public void setDependency(SuperHeroHelper dependency) {
        this.dependency = dependency;
    }
}

The above code is a very small DI container which works for our superhero story. The actual code of Spring is way more complex and advanced than the above code, but this should help you understand the basic concepts of DI and IOC. Please let me know your questions, objections through comments.


Stats:
779 views
Scaffold your ideas into application
Get your free alpha access now.
Only 445 left, Hurry!

Angular Directives Demystified

Directives are the most misunderstood aspect of angular JS. Learn how directives can help you keep your code clean.

Third wave of digital transformation

Third wave of digital transformation

Angularjs Tutorial: Understanding Scope

Scopes are one of the most important and rarely understood concept in angular, in this part we explore how scope works in angularjs.

Comments:

Leave your comments