這幾天在學習公司內部搜尋引擎客戶端的使用,發現裡面使用到了懶載入技術,趁機學習了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也是不利於使用者體驗,而運用懶載入則可以將頁面進...