import java.util.ArrayList; import java.util.List; /** * 裝飾器模式: 側重於對目標類中核心邏輯的擴展, 依然是以目標類爲中心 * 代理模式 : 側重於對目標類的訪問限制於處理,或者對其添加一些重用性且與 核心業務邏輯無關的功能, 例如日誌. */ public class ProxyModel { } interface IDao{ void add(Object o); void delete(Object o); void update(int id,Object o); Object find(int id); } class SimpleDao implements IDao{ private List<Object> mDataBase = new ArrayList<>(); @Override public void add(Object o) { mDataBase.add(o); } @Override public void delete(Object o) { mDataBase.remove(o); } @Override public void update(int id,Object o) { mDataBase.remove(id); mDataBase.add(id,o); } @Override public Object find(int id) { return mDataBase.get(id); } } class DaoProxy implements IDao{ private IDao iDao; public DaoProxy() { } public DaoProxy(IDao iDao) { this.iDao = iDao; } private void beginTransaction(){ System.out.println("開始操做數據庫"); } private void commit(){ System.out.println("結束操做數據庫"); } @Override public void add(Object o) { this.beginTransaction(); iDao.add(o); this.commit(); } @Override public void delete(Object o) { this.beginTransaction(); iDao.delete(o); this.commit(); } @Override public void update(int id, Object o) { this.beginTransaction(); iDao.update(id,o); this.commit(); } @Override public Object find(int id) { this.beginTransaction(); Object o = iDao.find(id); this.commit(); return o; } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; /** * 動態代理: 相對於靜態代理, 動態代理中的代理類不須要事先與目標類相同的接口, 並且不依賴於接口的具體實現, 理論上能夠代理全部類的全部方法. 但由於要考慮到涉及到的業務, 因此要求面向接口代理. * 實現機制: 運行時建立一個虛擬的代理類, 在代理的目標方式實際執行時, 經過java的反射技術獲取到該防範對象, 並在執行先後後添加須要的操做, 這須要實現一個`InvocationHandler接口 */ public class ProxyModel { public static void main(String[] args) { SimpleDao simpleDao = new SimpleDao(); IDao proxy = new DaoProxy().createProxy(simpleDao); proxy.add("ss"); } } interface IDao { void add(Object o); void delete(Object o); void update(int id, Object o); Object find(int id); } class SimpleDao implements IDao{ private List<Object> mDataBase = new ArrayList<>(); @Override public void add(Object o) { mDataBase.add(o); } @Override public void delete(Object o) { mDataBase.remove(o); } @Override public void update(int id,Object o) { mDataBase.remove(id); mDataBase.add(id,o); } @Override public Object find(int id) { return mDataBase.get(id); } } class DaoProxy { /*這裏須要注意, 返回值只能是一個接口, 而不能使具體的實現類. */ public IDao createProxy(IDao target) { /*此方法生成的虛擬類是根據目標的Class文件拿到的父類接口生成的, 所以不能強制轉換成實現類 */ return (IDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beginTransaction(); Object invoke = method.invoke(target, args); commit(); return invoke; } }); } private void beginTransaction() { System.out.println("讀寫開始前,開啓數據庫!"); } private void commit() { System.out.println("讀寫結束,關閉數據庫!"); } }
/** * 不關心接口的實現邏輯, 只須要取到備操做類便可. */ public class ProxyModel { public static void main(String[] args) { IDao proxy = new LogProxy().createProxy(SimpleDao.class); proxy.add("item"); proxy.delete("asd"); proxy.update(1,"asd"); } } interface IDao { void add(Object o); void delete(Object o); void update(int id, Object o); Object find(int id); } class SimpleDao implements IDao{ @Override public void add(Object o) { System.out.print("添加: "+o.toString()+" "); } @Override public void delete(Object o) { System.out.print("刪除: "+o.toString()+" "); } @Override public void update(int id,Object o) { System.out.print("更新: "+id+" "+o.toString()+" "); } @Override public Object find(int id) { System.out.print("查找: "+id+" "); return null; } } class LogProxy { public <T> T createProxy(Class<T> target) { return (T) Proxy.newProxyInstance(target.getClassLoader(), target.getInterfaces(), (proxy, method, args) -> { System.out.print("開始輸出日誌------->"); System.out.print("調用方法:" + method.getName() + makeArgsText(args)); method.invoke(target.newInstance(),args); System.out.print("<-------日誌輸出結束"); System.out.println(); return null; }); } private String makeArgsText(Object[] args) { StringBuilder builder = new StringBuilder(); builder.append(", 共有").append(args.length).append("個參數: "); for(Object item : args) { builder.append(item.toString()).append(" & "); } return builder.toString(); } }
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * 若是目標類沒有實現接口, 那麼`Spring AOP`會選擇使用`CGLIB`來動態代理目標類. * CGLIB(Code Generation Library), 是一個代碼生成的類庫, 能夠在運行時動態的生成某個類的子類. * CGLIB是經過繼承的方式作的動態代理, 所以若是某個類被標記爲Final,那麼它是沒法使用CGLIB作動態代理的. */ class SimpleDao { public void add(Object o) { System.out.println("添加: " + o.toString() + " "); } public void delete(Object o) { System.out.println("刪除: " + o.toString() + " "); } public void update(int id, Object o) { System.out.println("更新: " + id + " " + o.toString() + " "); } public Object find(int id) { System.out.println("查找: " + id + " "); return null; } } class MyMethodInterceptor implements MethodInterceptor { /** * sub:cglib生成的代理對象 * method:被代理對象方法 * objects:方法入參 * methodProxy: 代理方法 */ @Override public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("======插入前置通知======"); Object object = methodProxy.invokeSuper(sub, objects); System.out.println("======插入後者通知======"); return object; } } class Client { public static void main(String[] args) { // 經過CGLIB動態代理獲取代理對象的過程 Enhancer enhancer = new Enhancer(); // 設置enhancer對象的父類 enhancer.setSuperclass(SimpleDao.class); // 設置enhancer的回調對象 enhancer.setCallback(new MyMethodInterceptor()); // 建立代理對象 SimpleDao proxy = (SimpleDao) enhancer.create(); // 經過代理對象調用目標方法 proxy.add("add"); } }