0

我只知道用于 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;
}

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

4

2 回答 2

0

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

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

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

于 2013-06-21T05:20:14.400 回答
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()将使用实际对象填充类别父级。

在这段代码中:

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()方法实际上返回一个代理(不是实际对象)。代理上的第一个方法调用实际上会触发对象的加载。这里的代理用于延迟实际对象的实际检索,直到它真正需要它,即延迟加载

希望这能回答你的问题。

于 2013-06-21T07:05:23.290 回答