代理模式

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