动态与延迟加载

时间:2013-06-21 05:14:08

标签: java lazy-loading

我只知道用于AOP的动态代理 但是,它似乎也可以用于延迟加载 文章中的以下示例旨在证明这一点 但是我不明白这与普通存取器有什么不同,究竟是什么'懒惰'加载到这里? 任何帮助理解作者想要通过延迟加载意味着什么都是值得赞赏的。

private Category tupleToObject(Serializable[] tuple) {    
    Category category = new Category((String)tuple[1],
        (YearMonthDay) tuple[2]);
        category.setId((Long) tuple[0]);
    category.setParent(lazyGet((Long) tuple[3]));
    return category;
}


protected CategoryItf lazyGet(Long id) {    
    if (id == null) {        
    return null;    
    }    
    return (CategoryItf)Proxy.newProxyInstance( 
        CategoryItf.class.getClassLoader(),
        new Class[] { CategoryItf.class },
        new LazyLoadedObject() {
            protected Object loadObject() {
                return get(id);
            }        
    });
}


public abstract class LazyLoadedObject    implements InvocationHandler {
    private Object target;
    public Object invoke(Object proxy,
                         Method method, Object[] args)
                  throws Throwable {
        if (target == null) {
            target = loadObject();
        }
        return method.invoke(target, args);
    }
    protected abstract Object loadObject();
}

这与以下内容有何不同:

private Category tupleToObject(Serializable[] tuple) {    
    Category category = new Category((String)tuple[1],
        (YearMonthDay) tuple[2]);
        category.setId((Long) tuple[0]);
    category.setParent(get((Long) tuple[3]));
    return category;
}

在这两种情况下,只在需要时才创建父级。

2 个答案:

答案 0 :(得分:0)

以下代码段使实现“懒惰”:

private Object target;
public Object invoke(Object proxy,
                     Method method, Object[] args)
              throws Throwable {
    if (target == null) {
        target = loadObject();
    }

您可以看到,无论您多少次调用此代码,每次都会获得相同的对象。所以,实际上它是单身人士。但是它不是在程序开始时创建的,而是仅在第一次需要时才创建。这就是“懒惰”的含义。

答案 1 :(得分:0)

让我试着解释一下我对代码的理解:

在此代码中:

private Category tupleToObject(Serializable[] tuple) {    
    Category category = new Category((String)tuple[1],
        (YearMonthDay) tuple[2]);
        category.setId((Long) tuple[0]);
    category.setParent(get((Long) tuple[3]));
    return category;
}

get()方法将直接返回实际对象,因此调用tupleToObject()将使用实际对象填充类别parent。

在此代码中:

private Category tupleToObject(Serializable[] tuple) {    
    Category category = new Category((String)tuple[1],
        (YearMonthDay) tuple[2]);
        category.setId((Long) tuple[0]);
    category.setParent(lazyGet((Long) tuple[3]));
    return category;
}

lazyGet()方法实际上返回一个代理(不是实际的对象)。对代理的第一个方法调用实际上会触发对象的加载。此处的代理用于延迟实际对象的实际检索,直到实际需要,即延迟加载

希望这能回答你的问题。