Jiew Meng
Jiew Meng

Reputation: 88197

Creating a Simple Dependency Injection Container in Java, Dynamically creating objects

I want to create a simple dependency injection container in java. Something I can use in the following way:

DI.register(ITheInterface, ClassImplementingInterface);
obj = DI.create(ITheInterface);

How might the actual code implementing register & create look like?

UPDATE

Why I try to understand the link provided by @Bill, I want to understand whats wrong with my attempt:

public class Container {

    protected static Container instance;
    protected Hashtable<Class<?>, Class<?>> classMap;

    protected Container() {
        this.classMap = new Hashtable<Class<?>, Class<?>>();
    }

    public static Container getInstance() {
        if (Container.instance == null)
            Container.instance = new Container();
        return Container.instance;
    }

    public void register(Class<?> forInterface, Class<?> toUse) {
        this.classMap.put(forInterface, toUse);
    }

    public Object create(Class<?> forInterface) throws Exception {
        if (!this.classMap.containsKey(forInterface))
            throw new Exception("Dependency Ingection Container does not have a class registered for use with " + forInterface.getName());
        return this.classMap.get(forInterface).newInstance();
    }
}

The test code:

interface ITest {
    public String getName();
    public void setName(String name);
}

class Test1 implements ITest {

    protected String name;

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

}

public class Test {
    public static void main(String[] args) throws Exception {
        Container di = Container.getInstance();
        di.register(ITest.class, Test1.class);
        ITest t1 = (ITest)di.create(ITest.class);
        t1.setName("Yay!!!");
        System.out.println(t1.getName());
    }
}

The error I got:

Exception in thread "main" java.lang.IllegalAccessException: Class dependencyinjection.Container can not access a member of class Test1 with modifiers ""
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:95)
    at java.lang.Class.newInstance0(Class.java:366)
    at java.lang.Class.newInstance(Class.java:325)
    at dependencyinjection.Container.create(Container.java:27)
    at Test.main(Test.java:32)

UPDATE 2

I figured it will work when I make the class public. There is another problem, I want to create classes based on generic interfaces. eg.

Currently, if I do

di.register(IDataMapper<Event>.class, EventDataMapper.class);

I get IDataMapper and Event are not resolved to a variable

Upvotes: 3

Views: 5322

Answers (1)

Justin
Justin

Reputation: 4116

You can find a simple implementation of JSR 330 here

It is pretty easy to understand.

To answer your edits:

Test1 is a package private class Container is in another package does not have access to the Test1 constructor. You can work around this by doing the following:

Constructor c = this.classMap.get(forInterface).getDeclaredConstructor();
c.setAccessible(true);
return c.newInstance();

Upvotes: 4

Related Questions