懶載入的實現

2021-08-25 16:31:41 字數 3582 閱讀 1975

這幾天在學習公司內部搜尋引擎客戶端的使用,發現裡面使用到了懶載入技術,趁機學習了cglib的東西。

什麼是懶載入呢?其現象是這樣的,例如:

// 呼叫memberdao.find()方法時,不載入資料

memberdo member = memberdao.find("maomao");

// 呼叫member.getname()方法時,才去呼叫dao載入資料。這不同於傳統的使用習慣。

string name = member.getname();

這個是怎麼實現的呢?一開始受到搜尋引擎客戶端的影響走了彎路,它沒有充分使用到cglib的特性。

先簡單地介紹一下cglib裡的乙個類enhancer。這個類的主要作用是動態生成乙個類的子類,作動態**。

enhancer enhancer = new enhancer();

// 設定需要**的類

enhancer.setsuperclass(memberdo.class);

// 設定乙個callback的過濾器。說它是過濾器,還不如說它是callback的選擇器(比如執行哪個方法前,呼叫哪個callback),

// 它的乙個抽象方法int accept(method method) 返回的是callback陣列的下標

enhancer.setcallbackfilter(new defaultcallbackfilter());

// 這裡就是設定上面所提到的callback陣列

enhancer.setcallbacks(new callback );

// 返回乙個動態生成的子類

enhancer.create();

要實現的需求是,執行member.getname()才去載入資料。原理就是在執行member.getname()前,把資料從dao或從外部介面讀過來。 先看看我走彎路的實現方式:

public class memberdao ;

@override

public int accept(method method) else }}

/*** 方法***methodinterceptor的實現

* ** 這裡就是具體載入資料的實現

*

*/private class defaultmethodinterceptor implements methodinterceptor

// 從資料來源取資料

memberdo tmpmember = generatememberdo();

member.setname(tmpmember.getname());

member.set***(tmpmember.get***());

// 設定已經載入的標誌

// (這裡把是否載入的標記寫在do裡,不太好。我做一下實驗才這樣做的,為了簡單。寫在threadlocal是乙個方式,不會侵入到do)

member.setloaded(true);

return proxy.invokesuper(member, args);}}

/*** 查詢資料

* *

* 1.當lazy為true的時候,會為memberdo建立乙個動態**類,並設定好callbackfilter和methodinterceptor

* 2.當lazy為false的時候,直接從資料來源取資料

*

* * @param name 會員的名字

* @param lazy 是否使用懶載入

* @return

*/public memberdo find(string name, boolean lazy) );

return (memberdo) enhancer.create();

} else

}/**

* 模擬從資料來源取資料

* * @return

*/private memberdo generatememberdo()

}

看一下執行結果:

// 控制台顯示:query data from db.

memberdo member1 = memberdao.find("test", false);

// 控制台無顯示

memberdo member2 = memberdao.find("test", true);

// 控制台顯示:query data from db.

// 控制台顯示:name:maomao

system.out.println(string.format("name:%s", member2.getname()));

// 控制台顯示:already loaded.

// 控制台顯示:***:male

system.out.println(string.format("***:%s", member2.get***()));

從執行結果來看,使用了懶載入,在呼叫member2.getname()才去載入資料,在呼叫member2.get***()時候直接返回第一次載入的資料。

前面提到過上述的實現方式是我走的彎路,其實有更加簡潔的實現方式,cglib有專門用來實現懶載入的callback介面,名叫lazyloader。我們只要實現這個介面,寫上具體的資料載入方式。看乙個例子:

public class memberdao else

}/**

* 模擬從資料來源取資料

* * @return

*/private memberdo generatememberdo()

private class memberdolazyloader implements lazyloader

@override

public object loadobject() throws exception }}

最後來看看執行結果:

memberdao memberdao = new memberdao();

// 控制台顯示:query data from db.

memberdo member1 = memberdao.find("maomao", false);

memberdo member2 = memberdao.find("maomao", true);

// 控制台顯示:query data from db.

// 控制台顯示:name:maomao

system.out.println(string.format("name:%s", member2.getname()));

// 控制台顯示:***:male

system.out.println(string.format("***:%s", member2.get***()));

一樣的執行結果,而且簡單,沒有侵入。是不是比較簡單呢?

mysql 懶載入 懶載入和預載入實現解析

1.懶載入 懶載入的要點如下 1.進入可視區域之後請求資源 2.對於電商等較多,頁面很長的業務場景很適用 3.可以減少無效資源的載入 4.併發載入的資源過多會阻塞js的載入,影響 的正常使用 如何實現懶載入呢?要點就是html中img標籤src屬性為空,或者可以設定乙個載入中的友好提示,給乙個dat...

懶載入的實現原理?

意義 懶載入的主要目的就是作為伺服器前端的優化,減少請求次數或者延遲請求數。實現原理 先載入一部分資料,當觸發某個條件時利用非同步 async 載入剩餘的資料,新得到的資料不會影響原有資料的顯示,同時最大幅度的減少伺服器端資源耗用。實現方式 1.第一種是純粹的延遲載入,使用settimeout和se...

路由懶載入的實現

懶載入 也叫延遲載入,即在需要的時候進行載入,隨用隨載。為什麼需要懶載入?像vue這種單頁面應用,如果沒有應用懶載入,運用webpack打包後的檔案將會異常的大,造成進入首頁時,需要載入的內容過多,時間過長,會出啊先長時間的白屏,即使做了loading也是不利於使用者體驗,而運用懶載入則可以將頁面進...