JDK 動態代理基於 反射機制(java.lang.reflect),運行時動態生成實現目標接口的代理類。核心角色:
Singer);MySinger);InvocationHandler,攔截方法調用(如 Agent);Proxy.newProxyInstance() 生成,委託給 InvocationHandler。// 1. 服務接口
public interface Singer {
void sing();
String s();
}
// 2. 目標實現
public class MySinger implements Singer {
public void sing() { System.err.println("唱歌。。。。"); }
public String s() { return "Jay Chou"; }
}
// 3. 代理處理器(經紀人)
public class Agent implements InvocationHandler {
private Object target;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("開始事務");
System.out.println("判斷權限");
Object result = method.invoke(target, args); // 執行目標方法
System.out.println("結束事務");
return result;
}
}
// 4. 測試
public class Test {
public static void main(String[] args) {
Agent agent = new Agent();
Singer proxy = (Singer) agent.bind(new MySinger());
proxy.sing();
System.out.println(proxy.s());
}
}
Agent 可代理任意 Singer 實現;invoke,業務代碼純淨;@Aspect
@Component
public class TxAspect {
@Around("execution(* com.service.*.*(..))")
public Object txAdvice(ProceedingJoinPoint pjp) throws Throwable {
// 開啟事務
Object ret = pjp.proceed(); // 相當於 method.invoke()
// 提交/回滾事務
return ret;
}
}
Spring 將 InvocationHandler 抽象為 MethodInterceptor,配合切點表達式實現聲明式事務,本質同樣是動態代理模式。
invoke 中做耗時操作;Proxy.newProxyInstance(classLoader, interfaces, handler) 參數含義理解類加載器隔離問題;-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true 導出生成的代理類源碼分析。