Click here to Skip to main content
15,887,083 members
Articles / Programming Languages / Java
Tip/Trick

Simple IoC Container Base on ConcurrentHashMap

Rate me:
Please Sign up or sign in to vote.
3.50/5 (2 votes)
23 Jan 2015CPOL3 min read 14K   5
Is it easy to create an IoC container?

Introduction

Do you need an IoC container in your Java project? Are you familiar with XML hell of Spring IoC or is Google Guice flexible enough? Why don't you create your own IoC container with special requirement for your project?

I usually create some experiment code, it's too small to use Spring IoC with some XML file and Guice doesn't allow to modify container at runtime (there are some trick to do this but more code is needed and maybe don't support type check). I am also not familiar with annotation. So I decided to create my own tiny container. If you also want to create your own container, my article maybe helpful for you.

Background

Forget all complexity of DI and IoC definition, a simple IoC container can consider as a Map<Class,Object>. You can make an association between a Class and an Object, and you need a function with input parameter as Class and return according Object. Map can satisfy those requirements, but in multi-thread scene traditional Map has poor performance (the reason can be explained by another long article). So I chose ConcurrentHashMap designed by Doug Lea.

It's better if a container also supports type check.

Declare ConcurrentHashMap as Container

It's quite easy and simple like this:

Java
private ConcurrentHashMap<Class<?>, 
Object> container = new ConcurrentHashMap<Class<?>, Object>();

We will store Class and Object as a pair.

Register or Create Binding between Class and Object

Java
public <K, V extends K> boolean regit(Class<K> key, V value) {
    return container.put(key, value) == null;
}

The magic of Type check comes from:

Java
<K, V extends K>

This declares 2 classes: K and V inheritant K. If you put an object of class that doesn't extends K, Java compiler will raise an exception (In Eclipse IDE, you will not compile project).

Get Object Binding with Class

Java
public <K, V extends K> V resolve(Class<K> keyObject) {

    return (V) container.get(keyObject);
}

Because we checked type when we create binding, we don't have to check it again when we retrieve object.

More Features with regit(Class,Class)

I think regit(Class,Object) can solve most cases, but it's useful if we provide automatic creating object feature .

Java
public <K, V extends K> boolean regit(Class<K> key, Class<V> value)
        throws Exception {
    V object;
    try {
        object = ReflectHelper.createObject(this,value);
    } catch (Exception e) {
        throw e;
    }
    return (container.put(key, object) == null);
}

How can we create programmatic objects?

Java
public static <V> V createObject
(ITypeCheckContainer container, Class<V> v) throws Exception{
    V result = null;
    Constructor[] constructors = v.getConstructors();
    Constructor willBeImplemented = constructors[0];
    for(int i = 1; i <constructors.length; i++){
        if(willBeImplemented.getParameterCount() >
            constructors[i].getParameterCount()) willBeImplemented = constructors[i];
    }
    Parameter[] para = willBeImplemented.getParameters();
    Object[] objectPara = new Object[para.length];
    for(int i = 0;i < para.length;i++){
        Class<?> clazz = para[i].getType();
        objectPara[i] = container.resolve(clazz);
        if(objectPara[i] == null) return null;
    }
    try {
        result = (V) willBeImplemented.newInstance(objectPara);
    } catch (InstantiationException | IllegalAccessException
            | IllegalArgumentException | InvocationTargetException e) {

        throw e;
    }
    return result;
}

Package java.lang.reflect.* contains a lot of information about Class. We can do a lot of things with this package, programmatic creating object is just a small example.

Usage

Create a class or an interface name Father, and 2 other class Child1, Child2 inherited from Father. You can easy regit and get instance like this:

Java
//Regit
ITypeCheckContainer container = new ConcurrentHashMapContainer();
container.regit(Father.class, new Child1());
container.regit(Child2.class, new Child2());
//Resolve
container.resolve(Child1.class);
container.resolve(Child2.class).doSomething();

Performance Compare

 

I reuse and modify test scenario from this article http://java.dzone.com/articles/java-7-hashmap-vs (thanks to Pierre-Hugues Charbonneau for this useful article).

At one glance, I created some concurrent threads to get object from each container (number of threads is from 1 to 50), each scenario runs 5 times and I use average data for comparing. Details of results can be found at my Github repository.

Image 1

You can see FastIoC spend less time than Guice. On an average, FastIoC spends 0.001544 seconds, Guice spends 0.00264 seconds.

Conclusion

This tiny IoC container may be useful for small and experiment projects. Its code also demonstrates how to work with Generic of Java also about java.lang.reflect package.

Welcome any suggestion for improving source code, I will appreciate all comments. Please update the latest source code from my Github repository at https://github.com/vudangngoc/FastIoC.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Orchestra Networks
Vietnam Vietnam
Java programmer at Orchestra Networks

Comments and Discussions

 
SuggestionOptimizations Pin
Chad3F26-Jan-15 14:33
Chad3F26-Jan-15 14:33 
GeneralRe: Optimizations Pin
vudangngoc26-Jan-15 16:03
vudangngoc26-Jan-15 16:03 
Question[My vote of 2] Good for exercise, imo not good advice for actual use Pin
mrcellux23-Jan-15 7:09
mrcellux23-Jan-15 7:09 
AnswerRe: [My vote of 2] Good for exercise, imo not good advice for actual use Pin
vudangngoc23-Jan-15 9:09
vudangngoc23-Jan-15 9:09 
GeneralRe: [My vote of 2] Good for exercise, imo not good advice for actual use Pin
mrcellux23-Jan-15 9:58
mrcellux23-Jan-15 9:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.