代理模式

代理模式的優點:

  • 代理模式能將代理對象和真實被調用的目標對象分離
  • 在一定的程度降低系統的耦合性,擴展性好
  • 可以起到保護目標對象的作用
  • 可以增強目標對象的功能

代理模式的缺點

  • 代理模式造成系統設計類的數量增加
  • 在客戶端和目標對象中增加一個代理對象,會導致請求處理速度變慢
  • 增加系統的複雜度

靜態代理和動態代理的本質區別

  1. 靜態代理只能通過手動完成代理操作,如果被代理類增加的新的方法,代理類需要同步增加,違背的開閉原則
  2. 動態代理採用在運行時動態生成代碼的方式,取消了對被代理類的擴展限制,遵循開閉原則
  3. 若動態代理要對目標代理的增加邏輯進行擴展,結合策略模式,只需要新增策略變可以完成,無需修改代理類的代碼

CGLib 和 JDK 動態代理對比

  1. JDK動態代理實現了被代理對象的接口,CGLib 代理繼承了被代理對象
  2. JDK動態代理和CGLib代理都是在運行期生成字節碼文件,JDK動態代理直接寫Class字節碼,CGLib代理是使用ASM框架寫Class字節碼,CGLib代碼實現更復雜,生成的代碼裏類比JDK動態代理效率低
  3. JDK動態代理調用代理方法是通過反射機制調用的,CGLib代理是通過FastClass 機制直接調用方法的,CGLib代理的執行效率高

接下里分別使用JDK動態代理 和 CGLib 實現業務場景

JDK 動態代理生成對象的步驟:

  1. 獲取被代理對象的引用,並通過反射獲取它所有的接口
  2. JDK動態代理類生成一個新的類,同時新的類要實現被代理類實現的所有接口
  3. 動態生成java代碼,新加的業務邏輯方法由一定的邏輯代碼調用
  4. 編譯生成新的java代碼.class 文件
  5. 重新加載到JVM中

JDK 動態代理

 

創建一個人類的接口 person

/**
 * @Author Lxq
 * @Date 2020/3/24 17:21
 * @Version 1.0
 */
public interface Person {

    public void findLove();
}
創建一個單身客戶類 Customer
/**
 * @Author Lxq
 * @Date 2020/3/24 17:31
 * @Version 1.0
 * 單身客戶類
 */
public class Customer implements Person{
    @Override
    public void findLove() {
        System.out.println("身高180cm");
        System.out.println("高富帥");
        System.out.println("有8塊腹肌");
    }
}
媒婆的代理類 JDKMeipo 
/**
 * @Author Lxq
 * @Date 2020/3/24 17:24
 * @Version 1.0
 * JDK動態代理
 */
public class JDKMeipo implements InvocationHandler {

    // 被代理的對象,把引用保存下來
    private Object target;

    public Object getInstance(Object target) {
        this.target = target;
        Class<?> clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object invoke = method.invoke(this.target, args);
        after();
        return invoke;
    }

    private void before(){
        System.out.println("我是媒婆:我要給你找對象,現在確認一下你的要求");
        System.out.println("開始配對");
    }

    private void after(){
        System.out.println("如何合適,留下聯繫方式");
    }
}

 測試代理:

/**
 * @Author Lxq
 * @Date 2020/3/24 16:17
 * @Version 1.0
 */
public class Test {
    public static void main(String[] args) {
        Person person = (Person) new JDKMeipo().getInstance(new Customer());
        person.findLove();

    }
}

 

CGLib 代理 

CGLMeipo 代理類


/**
 * @Author Lxq
 * @Date 2020/3/24 17:37
 * @Version 1.0
 */
public class CGLMeipo implements MethodInterceptor {

    public Object getInStance(Class<?> clazz) {
        Enhancer enhancer = new Enhancer();
        // 要把那個設置生效爲即將生成的新的父類
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 業務的增強
        before();
        Object obj = methodProxy.invokeSuper(o, objects);
        after();
        return obj;
    }

    private void before(){
        System.out.println("我是媒婆:我要給你找對象,現在確認一下你的要求");
        System.out.println("開始配對");
    }

    private void after(){
        System.out.println("如何合適,留下聯繫方式");
    }
}

測試代理


/**
 * @Author Lxq
 * @Date 2020/3/24 16:17
 * @Version 1.0
 */
public class Test {
    public static void main(String[] args) {

        Customer customer = (Customer) new CGLMeipo().getInStance(Customer.class);
        customer.findLove();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章