Provide a surrogate or placeholder for another object to control access to it.
代理模式
抽象類
public abstract class AbstractSubject {
public abstract void work();
}
被代理對象
public class Subject extends AbstractSubject {
@Override
public void work() {
System.out.println(getClass() + " execute work()");
}
}
代理
public class Proxy extends AbstractSubject {
Subject subject;
@Override
public void work() {
System.out.println("Proxy call happening now");
// Lazy initialization
if (subject == null) {
subject = new Subject();
}
subject.work();
}
}
運行
public class Proxy extends AbstractSubject {
Subject subject;
@Override
public void work() {
System.out.println("Proxy call happening now");
// Lazy initialization
if (subject == null) {
subject = new Subject();
}
subject.work();
}
}
類圖
proxy.png
代理的作用:
- 延遲初始化被代理對象,僅當真正需要時才被初始化部蛇,特別是當被代理對象初始化比較消耗資源時梅桩。
- 可以在被代理對象的方法執(zhí)行前后膜眠,添加任意需要的動作肩民。
JAVA動態(tài)代理
JDK實現(xiàn)了代理模式,通過java.lang.reflect.Proxy.newProxyInstance
類來創(chuàng)建代理對象就斤,并且需要一個java.lang.reflect.InvocationHandler
接口的實現(xiàn)類控嗜,代理對象會實現(xiàn)被代理對象實現(xiàn)的接口,當調(diào)用代理對象的方法蒜茴,JDK就會執(zhí)行InvocationHandler.invoke()
方法星爪,此時給了我們添加額外動作的機會。
接口
public interface IFoo {
// 接口方法默認是public abstract的粉私,不需要添加修飾符
Object bar(Object obj);
}
實現(xiàn)類
public class Foo implements IFoo {
public Object bar(Object obj) {
System.out.println("Foo execute bar(obj)");
return obj;
}
}
InvocationHandler實現(xiàn)類
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DebugInvocationHandler implements InvocationHandler {
private Object obj;
private DebugInvocationHandler(Object obj) {
this.obj = obj;
}
public static Object newInstance(Object obj) {
// 返回代理對象
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(), // 類加載器
obj.getClass().getInterfaces(), // 被代理類實現(xiàn)的接口
new DebugInvocationHandler(obj)); // InvocationHandler實例
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
try {
System.out.println("before method " + method.getName());
result = method.invoke(obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
} finally {
System.out.println("after method " + method.getName());
}
return result;
}
}
執(zhí)行
public class Test {
public static void main(String[] args) {
/**
* java.lang.reflect.Proxy類需要一個java.lang.reflect.InvocationHandler對象
*
* Proxy.newProxyInstance()方法返回一個代理對象顽腾,該代理對象實現(xiàn)了被代理對象實現(xiàn)的接口(IFoo)
*
* 調(diào)用代理對象的方法,JDK就會執(zhí)行InvocationHandler.invoke()方法诺核,此時給了我們添加額外動作的機會
*/
IFoo proxy = (IFoo) DebugInvocationHandler.newInstance(new Foo());
proxy.bar(null);
}
}
Spring中的AOP就是通過代理來實現(xiàn)抄肖,有三種實現(xiàn)方式:動態(tài)代理久信,CGLIB,AspectJ 漓摩。
動態(tài)代理只能對存在接口的實現(xiàn)類進行代理裙士,CGLIB可以直接對類進行代理,AspectJ可以在類加載時織入幌甘。
參考: