結構型模式 - 代理模式 (Proxy Pattern)
代理模式是一種結構型設計模式,它允許通過代理對象來控制對另一個對象(目標對象)的訪問。代理對象充當目標對象的接口,客戶端通過代理對象間接訪問目標對象。
分為兩大類
- 靜態代理(編譯時就知道
- 動態代理(Java程序運行時才知道
Java 靜態代理
// 定義用戶服務接口
public interface UserService {// 添加用戶方法void addUser(String username);
}// 實現用戶服務接口的具體類
public class UserServiceImpl implements UserService {@Overridepublic void addUser(String username) {System.out.println("添加用戶: " + username);}
}// 用戶服務的代理類
public class UserServiceProxy implements UserService {// 持有目標對象private UserService target;public UserServiceProxy(UserService target) {this.target = target;}@Overridepublic void addUser(String username) {// 在調用目標方法之前添加額外邏輯,這里是打印日志System.out.println("開始添加用戶操作,記錄日志...");// 調用目標對象的方法target.addUser(username);// 在調用目標方法之后添加額外邏輯,這里是打印日志System.out.println("添加用戶操作完成,記錄日志...");}
}// 測試靜態代理的類
public class StaticProxyTest {public static void main(String[] args) {// 創建目標對象UserService target = new UserServiceImpl();// 創建代理對象,并將目標對象傳入UserService proxy = new UserServiceProxy(target);// 通過代理對象調用添加用戶方法proxy.addUser("張三");System.out.println();}
}
Java 動態代理又細分為兩類
- jdk 代理
- cglib 代理
// jdk 方式import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 業務接口
public interface UserService {void addUser(String username);
}// 業務接口實現類
public class UserServiceImpl implements UserService {@Overridepublic void addUser(String username) {System.out.println("添加用戶: " + username);}
}// 代理處理器
class UserServiceProxyHandler implements InvocationHandler {private final Object target;public UserServiceProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在調用目標方法之前添加額外邏輯System.out.println("開始執行添加用戶操作...");// 調用目標方法Object result = method.invoke(target, args);// 在調用目標方法之后添加額外邏輯System.out.println("添加用戶操作執行完畢。");return result;}
}// 測試類
public class JdkProxyExample {public static void main(String[] args) {// 創建目標對象UserService target = new UserServiceImpl();// 創建代理處理器UserServiceProxyHandler handler = new UserServiceProxyHandler(target);// 生成代理對象UserService proxy = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);// 調用代理對象的方法proxy.addUser("張三");}
}
// cglib 代理import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;// 業務類
public class UserManager {public void addUser(String username) {System.out.println("添加用戶: " + username);}
}// 代理攔截器
public class UserManagerInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {// 在調用目標方法之前添加額外邏輯System.out.println("開始執行添加用戶操作...");// 調用目標方法Object result = proxy.invokeSuper(obj, args);// 在調用目標方法之后添加額外邏輯System.out.println("添加用戶操作執行完畢。");return result;}
}// 測試類
public class CglibProxyExample {public static void main(String[] args) {// 創建 Enhancer 對象Enhancer enhancer = new Enhancer();// 設置父類enhancer.setSuperclass(UserManager.class);// 設置回調函數enhancer.setCallback(new UserManagerInterceptor());// 生成代理對象UserManager proxy = (UserManager) enhancer.create();// 調用代理對象的方法proxy.addUser("李四");}
}
對比分析
根本差異體現
代理機制
- JDK 代理:依賴接口。在 JDK 代理示例中,UserService 是一個接口,UserServiceImpl 實現了該接口,代理對象是基于接口生成的。
- CGLIB 代理:基于繼承。在 CGLIB 代理示例中,UserManage 是一個普通類,代理對象是 UserManage 的子類。
方法調用
- JDK 代理:在 InvocationHandler 的 invoke 方法中,使用 method.invoke(target, args) 調用目標對象的方法,這里的 target 是實際的目標對象。
- CGLIB 代理:在 MethodInterceptor 的 intercept 方法中,使用 proxy.invokeSuper(obj, args) 調用目標類的方法,obj 是代理對象本身。