之前介紹了代理模式,大家也都了解了代理模式,不過(guò)之前介紹的代理模式是靜態(tài)代理,靜態(tài)代理什么意思锐墙?靜態(tài)代理指的是代理類(lèi)是事先定義好的,在使用代理類(lèi)的時(shí)候也是明確初始化定義的代理類(lèi)长酗。但是如果有非常多的類(lèi)需要代理溪北,那么一個(gè)個(gè)那么定義靜態(tài)代理類(lèi)的工作量將是非常大的,其實(shí)JDK已經(jīng)給我們提供了現(xiàn)成的動(dòng)態(tài)代理類(lèi)夺脾,可以不用事先定義好所有的代理類(lèi)之拨,下面我們就介紹下JDK動(dòng)態(tài)代理類(lèi)。
JDK中動(dòng)態(tài)代理主要涉及到的是兩個(gè)類(lèi):java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy劳翰。下面我們先定義一下Subject接口和兩個(gè)功能一樣的實(shí)現(xiàn)類(lèi)用于測(cè)試敦锌。
Subject.java 接口類(lèi)
public interface Subject {
public String doSomething(String name);
}
RealSubject.java 實(shí)際提供功能的類(lèi)
public class RealSubject implements Subject {
@Override
public String doSomething(String name) {
System.out.println(name + " do something!");
return name + " do something!";
}
}
需要實(shí)現(xiàn)動(dòng)態(tài)代理功能的話實(shí)現(xiàn)一個(gè)代理類(lèi)實(shí)現(xiàn)InvocationHandler的接口,并實(shí)現(xiàn)invoke方法佳簸。
例子中實(shí)現(xiàn)DynamicProxyAOP類(lèi)用于在Subject類(lèi)前后分別實(shí)現(xiàn)其他功能乙墙,類(lèi)似AOP切面功能,其實(shí)Spring AOP的內(nèi)部核心實(shí)現(xiàn)就是通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)的生均√耄可以看到public Object invoke(Object proxy, Method method, Object[] args)方法有3個(gè)入?yún)ⅲ琾roxy表示代理類(lèi)马胧,method表示調(diào)用的Subject主類(lèi)的方法名汉买,args表示調(diào)用代理方法的參數(shù)數(shù)組,在內(nèi)部的具體實(shí)現(xiàn)我們通過(guò)反射方法通過(guò)method.invode來(lái)調(diào)用實(shí)際Subject方法佩脊。
public class DynamicProxyAOP implements InvocationHandler {
private Object subject;
public DynamicProxyAOP(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在執(zhí)行真實(shí)subject執(zhí)行的方法
System.out.println("before do something");
//執(zhí)行真實(shí)subject方法
Object rtn = method.invoke(subject, args);
//在執(zhí)行結(jié)束后再執(zhí)行的方法
System.out.println("after do something");
return rtn;
}
}
這樣就定義好了動(dòng)態(tài)代理的核心類(lèi)蛙粘,最后我們看下如何調(diào)用動(dòng)態(tài)代理類(lèi)。先分別定義RealSubject和RealSubject2兩個(gè)類(lèi)的對(duì)象威彰,再分別實(shí)現(xiàn)兩個(gè)DynamicProxyAOP的代理對(duì)象出牧,DynamicProxyAOP的入?yún)⒎謩e為這兩個(gè)Subject的對(duì)象。接下來(lái)我們創(chuàng)建動(dòng)態(tài)代理對(duì)象歇盼,通過(guò)調(diào)用Proxy的Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)來(lái)創(chuàng)建動(dòng)態(tài)代理對(duì)象舔痕,第一個(gè)參數(shù)為實(shí)現(xiàn)代理類(lèi)的ClassLoader,第二個(gè)參數(shù)為被代理類(lèi)的接口數(shù)組,最后一個(gè)參數(shù)為繼承自InvocationHandler的handler實(shí)現(xiàn)具體的代理功能伯复。
public class DynamicProxyMain {
public static void main(String[] args){
Subject realSubject = new RealSubject();
Subject realSubject2 = new RealSubject2();
InvocationHandler handler = new DynamicProxyAOP(realSubject);
InvocationHandler handler2 = new DynamicProxyAOP(realSubject2);
Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
handler);
Subject subject2 = (Subject) Proxy.newProxyInstance(realSubject2.getClass().getClassLoader(),
realSubject2.getClass().getInterfaces(),
handler2);
String rtn = subject.doSomething("tester ");
String rtn2 = subject2.doSomething("tester ");
}
}
從打印出的日志可以發(fā)現(xiàn)慨代,定義了兩個(gè)不同的繼承自Subject的類(lèi),但是動(dòng)態(tài)代理對(duì)象是動(dòng)態(tài)創(chuàng)建的啸如,不需要像靜態(tài)代理那樣侍匙,再為每一個(gè)Subject實(shí)現(xiàn)類(lèi)創(chuàng)建代理類(lèi),是不是很方便组底,后續(xù)大家如果要自己實(shí)現(xiàn)一些切面功能丈积,就可以通過(guò)動(dòng)態(tài)代理模式來(lái)實(shí)現(xiàn)筐骇,例如紀(jì)錄日至之類(lèi)的债鸡。
before do something
tester do something!
after do something
before do something
tester do something2!
after do something
本文實(shí)例中的源碼:https://github.com/feiweiwei/designpattern