代理模式的優點:
- 代理模式能將代理對象和真實被調用的目標對象分離
- 在一定的程度降低系統的耦合性,擴展性好
- 可以起到保護目標對象的作用
- 可以增強目標對象的功能
代理模式的缺點
- 代理模式造成系統設計類的數量增加
- 在客戶端和目標對象中增加一個代理對象,會導致請求處理速度變慢
- 增加系統的複雜度
靜態代理和動態代理的本質區別
- 靜態代理只能通過手動完成代理操作,如果被代理類增加的新的方法,代理類需要同步增加,違背的開閉原則
- 動態代理採用在運行時動態生成代碼的方式,取消了對被代理類的擴展限制,遵循開閉原則
- 若動態代理要對目標代理的增加邏輯進行擴展,結合策略模式,只需要新增策略變可以完成,無需修改代理類的代碼
CGLib 和 JDK 動態代理對比
- JDK動態代理實現了被代理對象的接口,CGLib 代理繼承了被代理對象
- JDK動態代理和CGLib代理都是在運行期生成字節碼文件,JDK動態代理直接寫Class字節碼,CGLib代理是使用ASM框架寫Class字節碼,CGLib代碼實現更復雜,生成的代碼裏類比JDK動態代理效率低
- JDK動態代理調用代理方法是通過反射機制調用的,CGLib代理是通過FastClass 機制直接調用方法的,CGLib代理的執行效率高
接下里分別使用JDK動態代理 和 CGLib 實現業務場景
JDK 動態代理生成對象的步驟:
- 獲取被代理對象的引用,並通過反射獲取它所有的接口
- JDK動態代理類生成一個新的類,同時新的類要實現被代理類實現的所有接口
- 動態生成java代碼,新加的業務邏輯方法由一定的邏輯代碼調用
- 編譯生成新的java代碼.class 文件
- 重新加載到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();
}
}