前言(可以直接跳過)
好久沒更新博客鹤树,最近都忙著和趙志文打王者榮耀,然后就是敲代碼了逊朽。動態(tài)代理這玩意昨天看到這個名詞罕伯,就想著什么鬼玩意。上網(wǎng)查了下是一種設計模式叽讳,就沒有細究了追他。然而今天剛學到Spring AOP 這一部分,瞬間懵比绽榛,怎么完全聽不懂馬老師在講什么玩意湿酸。為此我必須好好敏感下這玩意,通過40分鐘的刷知乎大概明白了怎么回事灭美。
正文
假設我們有一個業(yè)務邏輯那就是在某個類的每個方法運行的時候前后添加開始和結束的日志推溃。我們會怎么辦?首先我們看下代碼示例首先我們定義一個Person類的接口
public interface Person {
public void eat();
public void drink();
public void sleep();
public void WC();
}
> 然后是一個學生類的具體實現(xiàn)
> ```
public class Student implements Person {
@Override
public void eat() {
System.out.println("I am eating!");
}
@Override
public void drink() {
System.out.println("I am drinking!");
}
@Override
public void sleep() {
System.out.println("I am sleeping!");
}
@Override
public void WC() {
System.out.println("I am WCing!");
}
}
我們就是要在Student這個類的各個方法添加邏輯
- 很簡單就是直接在每個原方法上添加代碼届腐,很累铁坎,假設我給你500個方法你自己去添加吧。再者就是可能我不想改Student這個類了犁苏,我要改Teacher這個類硬萍,那么很麻煩要把Student這個類要還原,Teacher類又要重新添加围详。GG
- 靜態(tài)代理的思想就是朴乖, 看下面的代碼
public class StaticProxy implements Person {
private Person s = new Student();
@Override
public void eat() {
s.eat();
}
@Override
public void drink() {
s.drink();
}
@Override
public void sleep() {
s.sleep();
}
@Override
public void WC() {
s.WC();
}
}
3.很簡單實現(xiàn)Person接口然后再持有Student的引用,再添加助赞。有效解決了方法一的第二種情況买羞,可是添加500個方法我表示依然蛋疼。這時候就要出現(xiàn)我們的動態(tài)代理了動態(tài)代理的解決方案
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy implements InvocationHandler {
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("---Start---");
Object result = method.invoke(target, args);
System.out.println("---End---");
return result;
}
}
> ```
public class Test {
public static void main(String[] args) {
DynamicProxy proxy = new DynamicProxy();
Person s = (Person)proxy.bind(new Student());
s.drink();
s.sleep();
s.eat();
s.WC();
}
}
下面我來依照我自身的理解來說雹食,首先為什么要實現(xiàn)InvocationHandler這個接口畜普,因為從接口名字可以理解調(diào)用處理者,那么就是說我調(diào)用代理類的方法我肯定先調(diào)用invoke方法去執(zhí)行群叶,而不像一開始靜態(tài)代理里面那樣這些都是寫死的吃挑,那么bind方法是干嘛呢其實就是返回一個動態(tài)的代理類钝荡,這個代理類是根據(jù)傳入的對象和實現(xiàn)InvocationHandler這個接口的生成的。關于具體怎么實現(xiàn)抽個空研究下吧