1.靜態(tài)代理
靜態(tài)代理车吹,顧名思義,手動代碼代理醋闭。通過代理類實現(xiàn)被代理類的接口窄驹,進而完成代理過程。其實就是才能重寫了证逻,原本的接口方法乐埠,手動去在目標方法執(zhí)行前中后,進行切割囚企,進而實現(xiàn)代理丈咐。
public class TestStaticProxy {
public static void main(String[] args) {
IRegisterService iRegisterService = new RegisterServiceImpl();
IRegisterService proxy = new RegisterServiceProxy(iRegisterService);
proxy.register("RyanLee", "123");
}
}
interface IRegisterService {
void register(String name, String pwd);
}
class RegisterServiceImpl implements IRegisterService {
@Override
public void register(String name, String pwd) {
System.out.println(String.format("【向數(shù)據(jù)庫中插入數(shù)據(jù)】name:%s,pwd:%s", name, pwd));
}
}
class RegisterServiceProxy implements IRegisterService {
IRegisterService iRegisterService;
public RegisterServiceProxy(IRegisterService iRegisterService) {
this.iRegisterService = iRegisterService;
}
@Override
public void register(String name, String pwd) {
System.out.println("[Proxy]一些前置處理");
System.out.println(“開始執(zhí)行被代理的方法”);
iRegisterService.register(name, pwd);
System.out.println("[Proxy]一些后置處理");
}
}
2.JDK代理
JDK代理龙宏,動態(tài)代理類和被代理類必須繼承同一個接口棵逊。動態(tài)代理只能對接口中聲明的方法進行代理,有一定限制烦衣。每一個動態(tài)代理實例都有一個關(guān)聯(lián)的InvocationHandler歹河。通過代理實例調(diào)用方法,方法調(diào)用請求會被轉(zhuǎn)發(fā)給InvocationHandler的invoke方法花吟。(這里就可以看出為啥在實例化代理類時秸歧,要傳入目標類的接口,這樣在代理類實現(xiàn)的invoke方法里可以直接執(zhí)行接口方法實現(xiàn)了目標類被代理的過程)衅澈。實際上我們發(fā)現(xiàn)JDK的動態(tài)代理是基于反射的键菱,而實現(xiàn)方式和靜態(tài)代理很像,那為啥又說是動態(tài)代理呢今布?其實经备,細心的小伙伴就已經(jīng)發(fā)現(xiàn),JDK動態(tài)代理這種方式是一種對目標方法的增強部默,他不關(guān)心你目標方法侵蒙,而是通過newProxyInstance方法來生成新的 的代理對象,只管代理執(zhí)行傅蹂,此處解耦纷闺。而對比靜態(tài)代理就需要靜態(tài)代理類知道目標類的信息算凿,實現(xiàn)目標類的接口,限制很多犁功。而動態(tài)代理在實現(xiàn)代理的時候,是傳遞需要代理類,的實現(xiàn),無關(guān)接口 所以并不需要為每一種接口都寫一個代理類了氓轰。
public static void main(String[] args) {
Target tar = new Target();
ProxyHandler handler = new ProxyHandler();
BBQ proxy = (BBQ) handler.getProxy(tar);
proxy.sayBBQ("LF");
}
static class Target implements BBQ {
@Override
public void sayBBQ(String s) {
System.out.println("這是原方法執(zhí)行的 say bbq " + s);
}
}
interface BBQ {
void sayBBQ(String s);
}
static class ProxyHandler implements InvocationHandler {
Object obj;
public Object getProxy(Object obj) {
this.obj = obj;
Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
return o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
doBefore();
Object result = method.invoke(obj, args);
doAfter();
return result;
}
private void doBefore() {
Thread thread = Thread.currentThread();
System.out.println("[Proxy]一些前置處理" + thread.getName() + " " + thread.getId());
}
private void doAfter() {
System.out.println("[Proxy]一些后置處理");
}
}
3.cglib代理
JDK的動態(tài)代理機制只能代理實現(xiàn)了接口的類,而不能實現(xiàn)接口的類就不能實現(xiàn)JDK的動態(tài)代理浸卦,cglib是針對類來實現(xiàn)代理的署鸡,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強限嫌,但因為采用的是繼承靴庆,所以不能對final修飾的類進行代理。
public static void main(String[] args) {
Target tar = new Target();
CGLIBProxyDemo handler = new CGLIBProxyDemo();
Target proxy = (Target) handler.getProxy(tar);
proxy.sayBBQ("cglib代理");
}
static class Target implements JDKProxyUtil.BBQ {
@Override
public void sayBBQ(String s) {
System.out.println("這是原方法執(zhí)行的 say bbq " + s);
}
}
interface BBQ {
void sayBBQ(String s);
}
static class CGLIBProxyDemo implements MethodInterceptor {
private Object target;
public Object getProxy(Object obj) {
this.target = obj;
Enhancer enhancer = new Enhancer();
//生成子類
enhancer.setSuperclass(this.target.getClass());
// 回調(diào)方法
enhancer.setCallback(this);
// 創(chuàng)建代理對象
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] param, MethodProxy methodProxy) throws Throwable {
doBefore();
Object result = methodProxy.invokeSuper(obj, param);
doAfter();
return result;
}
private void doBefore() {
Thread thread = Thread.currentThread();
System.out.println("[Proxy]一些前置處理" + thread.getName() + " " + thread.getId());
}
private void doAfter() {
System.out.println("[Proxy]一些后置處理");
}
}
結(jié)語
仔細觀察會發(fā)現(xiàn):的原理依據(jù)萤皂,就是多態(tài)撒穷,要么實現(xiàn)接口生成代理類,要么繼承目標類生成代理類裆熙,而的手段就是反射端礼,利用反射來獲取被代理類的信息,進而才能實現(xiàn)不需要了解目標信息來構(gòu)建多態(tài)入录,從而動態(tài)解耦蛤奥。