動態代理: 顧名思義代理物件的類是通過動態方式來自動生成的,這樣的好處是, 我們不需要每次為被代理物件單獨創建代理類, JDK API 中, 對動態代理模式提供了支持,
JDK 的動態代理支持 :
java.lang.reflect.Proxy:生成動態代理類和物件;
java.lang.reflect.InvocationHandler(處理器介面):可以通過invoke方法實作對真實角色的代理訪問,每次通過 Proxy 生成的代理類物件都要指定對應的處理器物件,
CGLIB實作動態代理 :
CGLIB是高性能的代碼生成包, 可以為沒有實作介面的類提供代理, 是JDK動態代理必須要有介面的補充,
通常可以使用Java的動態代理創建代理, 但當要代理的類沒有實作介面或者為了更好的性能, CGLIB是一個好的選擇,
CGLIB作為一個開源專案, 代碼托管在github, 地址為: https://github.com/cglib/cglib
舉例說明:操作員查詢銷售訂單功能, 為了提高查詢性能, 我們接入快取功能, 如果快取中有資料, 那么直接回傳快取中的資料,;如果快取中沒有資料, 那么查詢訂單資料后, 把資料加入到快取, 這樣在下次查詢訂單資料時, 就可以從快取中讀取了,
a.創建訂單類、模擬的資料庫類、模擬的快取類;
//模擬的資料庫類:提供getOrder方法來通過oid查詢訂單資訊
public class DB {
private static List<Order> list = new ArrayList<>();
static{
list.add(new Order(1,"毛巾3條",45,"2020-2-1"));
list.add(new Order(2,"小紙巾10包",12,"2020-1-21"));
list.add(new Order(3,"洗發水1瓶",32,"2020-1-30"));
list.add(new Order(4,"紅牛1箱",36,"2020-2-2"));
list.add(new Order(5,"哈脾2箱",120,"2020-2-3"));
}
public Order getOrder(int oid){
System.out.println("從資料庫中查找資料...");
for(Order order:list){
if(order.getOid() == oid){
return order;
}
}
return null;
}
}
//模擬的快取類:提供getCache方法來通過oid查詢訂單資訊; 提供putCache方法將訂單資訊存放到快取中;
public class Cache {
private Map<Integer,Order> map = new HashMap();
private volatile static Cache cache;
private Cache(){
}
//雙檢 + 單例模式
public static Cache getInstance(){
if (cache == null){
synchronized (Cache.class){
if (cache == null){
cache = new Cache();
}
}
}
return cache;
}
//把訂單添加到快取中
public void putCache(int key, Order value){
System.out.println("把訂單資料添加到快取中...");
map.put(key,value);
}
//從快取中獲取訂單
public Order getCache(int key){
System.out.println("從快取中查詢訂單資料...");
return map.get(key);
}
}
b.定義業務類(被代理的物件類)介面,以供業務類和代理類去實作;
public interface OrderDao {
public Order queryOrder(int oid);
}
c.定義業務類、代理類實作業務類(被代理的物件類)介面;
public class OrderDaoImpl implements OrderDao {
@Override
public Order queryOrder(int oid) {
DB db = new DB();
Order order = db.getOrder(oid);
return order;
}
}
d.定義動態代理類工廠,以創建代理物件;
public class ProxyFactory implements InvocationHandler {
private Object target; //被代理的物件
//創建代理物件的方法
public Object create(Object target){
this.target = target;
//JDK 提供動態創建代理類物件的方法(代理物件類加載器,代理物件的介面集合,InvocationHandler(代理物件的處理器))
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
return proxy;
}
/**
* 生成的代理物件要執行的代理業務方法
* @param proxy:代理類物件
* @param method:被代理物件的方法
* @param args:被代理物件方法的引數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Order order = null;
if(null != args){
int oid = (int) args[0];
order = Cache.getInstance().getCache(oid);
if(null == order){
//呼叫真實的業務方法
order = (Order)method.invoke(target,args);
Cache.getInstance().putCache(order.getOid(),order);
}
}
return order;
}
}
測驗對比:
public class Test {
public static void main(String[] args) {
OrderDao od = new OrderDaoImpl();
ProxyFactory proxyFactory = new ProxyFactory();
OrderDao proxy = (OrderDao)proxyFactory.create(od); //創建代理物件,od是被代理物件
Order order = proxy.queryOrder(3);
System.out.println(order);
System.out.println("------------第二次查詢----------");
Order order1 = proxy.queryOrder(3);
System.out.println(order1);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/134993.html
標籤:其他
