Java設計模式之005--動態代理模式

動態代理: 顧名思義代理對象的類是經過動態方式來自動生成的。這樣的好處是, 咱們不須要每次爲被代理對象單首創建代理類, JDK API 中, 對動態代理模式提供了支持。java

JDK 的動態代理支持 :git

  java.lang.reflect.Proxy:生成動態代理類和對象;
github

  java.lang.reflect.InvocationHandler(處理器接口):能夠經過invoke方法實現對真實角色的代理訪問。每次經過 Proxy 生成的代理類對象都要指定對應的處理器對象。
數據庫

CGLIB實現動態代理 :緩存

  CGLIB是高性能的代碼生成包。 能夠爲沒有實現接口的類提供代理, 是JDK動態代理必需要有接口的補充。ide

  一般能夠使用Java的動態代理建立代理, 但當要代理的類沒有實現接口或者爲了更好的性能, CGLIB是一個好的選擇。性能

  CGLIB做爲一個開源項目, 代碼託管在github, 地址爲: https://github.com/cglib/cglib

舉例說明:操做員查詢銷售訂單功能, 爲了提升查詢性能, 咱們接入緩存功能, 若是緩存中有數據, 那麼直接返回緩存中的數據,;若是緩存中沒有數據, 那麼查詢訂單數據後, 把數據加入到緩存, 這樣在下次查詢訂單數據時, 就能夠從緩存中讀取了。
測試

a.建立訂單類、模擬的數據庫類、模擬的緩存類;this

//模擬的數據庫類:提供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.定義業務類(被代理的對象類)接口,以供業務類和代理類去實現;spa

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);    }}
相關文章
相關標籤/搜索