Java java.lang.reflect 套件提供動態代理能力:運行時生成實現指定介面的代理類,將方法呼叫轉發給指定處理器。核心三角色:

// InvocationHandler 唯一必須實作的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
// Proxy 建立代理實例的靜態工廠方法
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h);
關鍵: 代理類非開發者撰寫,業務邏輯集中於 InvocationHandler.invoke() 中。
public interface Person {
String getName(); String getGender();
void setName(String name); void setGender(String gender);
void setRate(int rate); int getRate();
}
public class PersonImpl implements Person {
private String name, gender, interests;
private int rate;
// 標準 getter/setter 略
}
public class OwnerInvocationHandler implements InvocationHandler {
private Person target;
public OwnerInvocationHandler(Person target) { this.target = target; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (methodName.startsWith("get")) {
return method.invoke(target, args); // 所有 get 允許
} else if (methodName.equals("setRate")) {
throw new IllegalAccessException("Access deny"); // 禁止 setRate
} else if (methodName.startsWith("set")) {
return method.invoke(target, args); // 其他 set 允許
}
return null;
}
}
public class NonOwnerInvocationHandler implements InvocationHandler {
private Person target;
public NonOwnerInvocationHandler(Person target) { this.target = target; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (methodName.startsWith("get") || methodName.equals("setRate")) {
return method.invoke(target, args); // get + setRate 允許
}
System.out.println("non method invoke: " + methodName);
return null; // 其他 set 拒絕
}
}
public class MyDynamicProxy {
public Person getOwnerProxy(Person person) {
return (Person) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}
public Person getNonOwnerProxy(Person person) {
return (Person) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new NonOwnerInvocationHandler(person));
}
public static void main(String[] args) {
MyDynamicProxy factory = new MyDynamicProxy();
// 本人代理測試
Person p1 = new PersonImpl(); p1.setName("Remy"); p1.setGender("Girl"); p1.setRate(1);
Person ownerProxy = factory.getOwnerProxy(p1);
System.out.println(ownerProxy.getName()); // Remy
try { ownerProxy.setRate(2); }
catch (Exception e) { System.out.println("can not setRate"); } // 攔截
// 他人代理測試
Person p2 = new PersonImpl(); p2.setName("Remy"); p2.setGender("Girl"); p2.setRate(1);
Person nonOwnerProxy = factory.getNonOwnerProxy(p2);
System.out.println(nonOwnerProxy.getName()); // Remy
nonOwnerProxy.setRate(2); // 允許
System.out.println(nonOwnerProxy.getRate()); // 2
}
}
Remy
can not setRate
Remy
2
Java 動態代理以 InvocationHandler 集中處理方法攔截邏輯,配合 Proxy.newProxyInstance() 運行時生成代理類,實現非侵入式的橫切關注點分離。本例展示權限控制經典應用,掌握「介面 + 實作 + 多種 Handler + Proxy 工廠」模式,即可靈活應用於 AOP、遠程調用、延遲載入等場景。