Java惰性实例化使用控制容器的反转

时间:2013-12-27 10:30:08

标签: java dependency-injection lazy-loading containers ioc-container

我有这个容器:

public class DIContainer {
    protected static DIContainer instance;
    protected Hashtable<Class<?>, Class<?>> classMap;

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

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

    public void regClass(Class<?> interf, Class<?> classToReg){
        this.classMap.put(interf, classToReg);
    }

    public Object create(Class<?> interf, boolean lazy) throws Exception{
        if(!this.classMap.containsKey(interf))
            throw new Exception("No such class registered with "+interf.getName()+" interface");
        else if(lazy == false)
            return this.classMap.get(interf).newInstance();
        else
            return this.classMap.get(interf);

    }
}

如果选择了延迟创建选项,我需要延迟创建一个对象(因此它会创建一个实现相同接口的子对象)。因此,当为该子对象调用第一个方法时,它将实例化“真实”对象。我怎么能这样做,因为我不知道将使用的确切方法?如何检查是否为该对象调用了任何方法?

现在我只尝试了懒惰的创作,你可以看到: return this.classMap.get(interf);

但它给了我一个错误:java.lang.ClassCastException 我是否需要一些其他方法来检查是否对该子对象进行了任何调用,因为在创建完成后,我将使用'create'方法,并且当调用方法时我需要以某种方式检查它?

这是我的测试界面及其实现类:

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

public class Class1 implements Interface1{
    String name;
    Class1(){}

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

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


}

这就是我测试它的方式:

public class Main {

    public static void main(String[] args) throws Exception{
        DIContainer dic = DIContainer.getInstance();
        dic.regClass(Interface1.class, Class1.class);
        Interface1 t1 = (Interface1) dic.create(Interface1.class, true);

P.S。如果我将懒惰创建设置为false,那么它就可以工作。

1 个答案:

答案 0 :(得分:0)

在您的情况下,行return this.classMap.get(interf);会返回一个Class对象,您之前使用this.classMap.put(interf, classToReg)行放入该对象。 Class对象肯定无法转换为Interface1接口,因为它没有实现它,从而导致ClassCastException

你真正需要的是返回一种实现Interface1接口并包装懒惰实例化类的包装器。当调用任何接口的方法时,包装器实例化实际对象并委托调用。

如果你想lazy-init一个任意的类,最直接的选择是使用Java的dynamic proxy