代理模式的定義:因爲某些緣由須要給某對象提供一個代理以控制對該對象的訪問。這時,訪問對象不適合或者不能直接引用目標對象,代理對象做爲訪問對象和目標對象之間的中介。java
代理模式的主要優勢有:
代理模式在客戶端與目標對象之間起到一箇中介做用和保護目標對象的做用;
代理對象能夠擴展目標對象的功能;
代理模式能將客戶端與目標對象分離,在必定程度上下降了系統的耦合度;spring
其主要缺點是:
在客戶端和目標對象之間增長一個代理對象,會形成請求處理速度變慢;
增長了系統的複雜度;sql
代理模式的主要角色以下。
抽象主題(Subject)類:經過接口或抽象類聲明真實主題和代理對象實現的業務方法。
真實主題(Real Subject)類:實現了抽象主題中的具體業務,是代理對象所表明的真實對象,是最終要引用的對象。
代理(Proxy)類:提供了與真實主題相同的接口,其內部含有對真實主題的引用,它能夠訪問、控制或擴展真實主題的功能。shell
在代理模式中動態代理是在各個框架中使用最普遍的一種設計模式,dubbo中 feign中 mybaits中,都有使用到動態代理。在dubbo中,在接口上添加@refrence ,dubbo就會根據這個接口生成一個代理實例來供消費者用生產者。在feign中也是同樣;mybatis中你只要指定包掃描的路徑,就會在spring中注入一個mapper,實際上這個mapper就是根據接口和xml生成的代理對象。實際上,這種「申明式的」功能實現方式,都是經過代理模式來實現的。設計模式
下面咱們經過cglib來寫一個「殘疾縮水」版的mybatis:安全
首先要整一個xml,我這裏用properties代替服務器
test.properties:mybatis
testA=select * from user where id= testB=select * from user where username=
再整一個接口:app
interface Test { String testA(int id); String testB(String username); }
再是代碼加強處理器,這裏面完成對接口的代理邏輯框架
class MyInvokationHandler implements MethodInterceptor { private static Map<String,String> sqlMap; { HashMap<String, String> map = new HashMap<>(); Properties prop = new Properties(); InputStream in = SystemMenuController.class.getClassLoader().getResourceAsStream("test.properties"); try { prop.load(in); Iterator<String> it = prop.stringPropertyNames().iterator(); while (it.hasNext()) { String key = it.next(); map.put(key,prop.getProperty(key)); } in.close(); } catch (java.io.IOException e) { e.printStackTrace(); } sqlMap=map; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { String name = method.getName(); String s = sqlMap.get(name); return s+objects[0]; } }
包掃描和啓動時注入容器略,數據源也略,用個main方法模擬一下:
public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Test.class); enhancer.setCallback(new MyInvokationHandler()); Test test = (Test) enhancer.create(); System.out.println(test.testA(1)); System.out.println(test.testB("hhh")); }
最終在控制檯中打印:
select * from user where id=1 select * from user where id=hhh
代理模式是一個很強大實用性很強的模式,動態代理大大減小了咱們的開發任務,同時減小了對業務接口的依賴,下降了耦合度。代理模式的使用場景能夠總結爲: