Java 动态加载与延迟加载

Java 动态加载与延迟加载,java,lazy-loading,Java,Lazy Loading,我只知道动态代理用于AOP。 但是,它似乎也可以用于延迟加载。 以下文章示例旨在说明这一点。 但是,我无法理解这与普通访问器有何不同,这里“延迟”加载的究竟是什么? 任何有助于理解作者所说的延迟加载的意思的帮助都是非常感谢的 private Category tupleToObject(Serializable[] tuple) { Category category = new Category((String)tuple[1], (YearMonthDay)

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

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

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


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

让我试着从我对代码的理解来解释:

在此代码中:

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;
}
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;
}
get()
方法将直接返回实际对象,因此调用
tupleToObject()
将用实际对象填充类别父对象

在本规范中:

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


希望这能回答您的问题。

经过编辑,使我的问题更加集中。AlexR,我没有得到我的答案,也无法将我的问题作为新问题提出来,现在问题太少了,请在这里帮助我。。即使是“get”也只会在第一次调用时返回实例?这有什么不同吗?我可以理解动态加载位,但不能理解“lazy”在这里的适用性。
tupleToObject()
-->
get()
-->
loaded object
。将其与:
tupleToObject()
-->
lazyGet()
-->
PROXY
。如果没有调用
代理上任何方法的代码
,实际对象将永远不会加载。如果在代码中的某个地方访问代理,即
PROXY.xxx
,则
PROXY
-->
loaded object
称为lazy,因为它不直接加载。