代理即代替主角完成額外操作。如明星有經紀人:洽談片酬、安排行程(前置操作),明星拍戲(核心業務),拍完後經紀人清算片酬(後置操作)。
Java 代理機制:在目標方法執行前後插入額外邏輯(安全檢查、日誌、事務等)。分為靜態代理和動態代理。
// 目標接口
public interface LoginService { void login(); }
// 目標實現
public class LoginServiceImpl implements LoginService {
@Override public void login() { System.out.println("login"); }
}
// 靜態代理類(手寫)
public class LoginServiceProxy implements LoginService {
private LoginService loginService;
public LoginServiceProxy(LoginService loginService) { this.loginService = loginService; }
@Override public void login() {
beforeLogin();
loginService.login();
afterLogin();
}
private void beforeLogin() { System.out.println("before login"); }
private void afterLogin() { System.out.println("after login"); }
}
// 客戶端
public class Client {
@Test public void test() {
LoginService loginService = new LoginServiceImpl();
LoginService proxy = new LoginServiceProxy(loginService);
proxy.login();
}
}
// 輸出:before login → login → after login
LoginService)LoginServiceImpl)運行時根據目標接口動態生成代理類字節碼,加載至 JVM,編譯期無 .class 文件。
// 代理處理器(核心邏輯)
public class ProxyInvocationHandler implements InvocationHandler {
private LoginService loginService;
public ProxyInvocationHandler(LoginService loginService) { this.loginService = loginService; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeLogin();
Object result = method.invoke(loginService, args); // 反射調用目標方法
afterLogin();
return result;
}
private void beforeLogin() { System.out.println("before login"); }
private void afterLogin() { System.out.println("after login"); }
}
// 客戶端創建代理
public class Client {
@Test public void test() {
LoginService target = new LoginServiceImpl();
ProxyInvocationHandler handler = new ProxyInvocationHandler(target);
// 動態生成代理對象
LoginService proxy = (LoginService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler
);
proxy.login();
// 可選:導出生成的代理類字節碼用於分析
createProxyClassFile();
}
public static void createProxyClassFile() {
String name = "LoginServiceProxy";
byte[] data = ProxyGenerator.generateProxyClass(name, new Class[]{LoginService.class});
try (FileOutputStream out = new FileOutputStream("/Users/" + name + ".class")) {
out.write(data);
} catch (Exception e) { e.printStackTrace(); }
}
}
// 輸出:before login → login → after login
代理調用處理器接口,每個代理對象關聯一個處理器。核心方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
代理對象調用任何接口方法時,均委派給此 invoke 方法。
提供靜態方法創建動態代理類和實例。生成的代理類均繼承 Proxy。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader:加載代理類的類加載器interfaces:代理類實現的接口列表h:調用處理器InvocationHandler,重寫 invoke 定義代理邏輯Proxy.newProxyInstance() 創建代理對象《深入淺出 JDK 動態代理(二)》將深入源碼分析:
invoke?ProxyGenerator 生成字節碼的細節敬請期待!