共計(jì) 2820 個(gè)字符,預(yù)計(jì)需要花費(fèi) 8 分鐘才能閱讀完成。
Java 動(dòng)態(tài)代理可以通過以下幾種方式實(shí)現(xiàn):
- 使用
java.lang.reflect.Proxy
類:Proxy
類提供了一個(gè)靜態(tài)方法newProxyInstance()
,可以通過傳入目標(biāo)對(duì)象的類加載器、目標(biāo)對(duì)象實(shí)現(xiàn)的接口和InvocationHandler
接口的實(shí)現(xiàn)類來創(chuàng)建代理對(duì)象。InvocationHandler
接口的實(shí)現(xiàn)類負(fù)責(zé)處理代理對(duì)象的方法調(diào)用。代理對(duì)象在調(diào)用方法時(shí),會(huì)把方法調(diào)用轉(zhuǎn)發(fā)給InvocationHandler
的invoke()
方法,從而實(shí)現(xiàn)代理功能。
public interface Subject {void doSomething();
}
public class RealSubject implements Subject {public void doSomething() {System.out.println("RealSubject doSomething");
}
}
public class MyInvocationHandler implements InvocationHandler {private Subject target;
public MyInvocationHandler(Subject target) {this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method invoke");
Object result = method.invoke(target, args);
System.out.println("After method invoke");
return result;
}
}
public class Main {public static void main(String[] args) {Subject realSubject = new RealSubject();
Subject proxySubject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
new MyInvocationHandler(realSubject));
proxySubject.doSomething();}
}
- 使用
CGLib
庫(kù):CGLib
是一個(gè)基于ASM
框架的字節(jié)碼生成庫(kù),它可以在運(yùn)行時(shí)動(dòng)態(tài)生成目標(biāo)對(duì)象的子類,并覆蓋其中的方法以實(shí)現(xiàn)代理功能。
public interface Subject {void doSomething();
}
public class RealSubject implements Subject {public void doSomething() {System.out.println("RealSubject doSomething");
}
}
public class MyMethodInterceptor implements MethodInterceptor {public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method invoke");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method invoke");
return result;
}
}
public class Main {public static void main(String[] args) {Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new MyMethodInterceptor());
Subject proxySubject = (Subject) enhancer.create();
proxySubject.doSomething();}
}
需要注意的是,使用 CGLib
實(shí)現(xiàn)動(dòng)態(tài)代理時(shí),目標(biāo)對(duì)象不能是 final
類或者包含 final
方法,因?yàn)?CGLib
是通過生成目標(biāo)對(duì)象的子類來實(shí)現(xiàn)代理的。
- 使用
ByteBuddy
庫(kù):ByteBuddy
是一個(gè)輕量級(jí)的字節(jié)碼操作庫(kù),它可以在運(yùn)行時(shí)動(dòng)態(tài)生成目標(biāo)對(duì)象的子類,并覆蓋其中的方法以實(shí)現(xiàn)代理功能。
public interface Subject {void doSomething();
}
public class RealSubject implements Subject {public void doSomething() {System.out.println("RealSubject doSomething");
}
}
public class MyInterceptor implements MethodInterceptor {public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method invoke");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method invoke");
return result;
}
}
public class Main {public static void main(String[] args) throws Exception {Class<? extends Subject> proxyClass = new ByteBuddy()
.subclass(Subject.class)
.method(any()).intercept(MethodDelegation.to(MyInterceptor.class))
.make()
.load(RealSubject.class.getClassLoader())
.getLoaded();
Subject proxySubject = proxyClass.getDeclaredConstructor().newInstance();
proxySubject.doSomething();}
}
需要注意的是,使用 ByteBuddy
實(shí)現(xiàn)動(dòng)態(tài)代理時(shí),需要引入 net.bytebuddy:byte-buddy
和net.bytebuddy:byte-buddy-agent
兩個(gè)依賴。
丸趣 TV 網(wǎng) – 提供最優(yōu)質(zhì)的資源集合!
正文完