2013-06-21 187 views
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; 
} 

在這兩種情況下,在需要的時候家長只被創建。

回答

0

下面的代碼片段使實現「懶」:

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

你可以看到,無論多少次,你都調用此代碼每次得到相同的對象。所以,實際上它是單身人士。但是,它不是在程序開始時創建的,而僅在第一次需要時才創建。這裏是「懶惰」的意思。

+0

編輯使我的問題更加集中。 – IUnknown

+0

AlexR,我沒有得到我的答案,並不能提出我的問題作爲新的,它現在太下了列表,請幫助我在這裏.. http://stackoverflow.com/questions/17220399/cannot-instantiate-a -class-using-a-button –

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()方法實際上返回代理(不是實際的對象)。對代理的第一個方法調用實際上會觸發加載對象。此處的代理用於延遲實際對象的實際檢索,直到其實際需要,即延遲加載

希望這回答你的問題。

+0

即使'get'也只會在第一次調用時返回一個實例嗎?它有什麼不同嗎?我可以理解動態加載位 - 但不是'懶惰'在這裏適合的。 – IUnknown

+0

'tupleToObject()' - >'get()' - >'loaded object'。將它與: 'tupleToObject()' - >'lazyGet()' - >'PROXY'。如果你沒有一個代碼調用'PROXY'上的任何方法,實際的對象將永遠不會被加載。如果你的代碼中的某處訪問PROXY,即PROXY.xxx,然後PROXY,加載對象,它就叫做_lazy_,因爲它不直接加載IMHO。 – user2507946