前面做了一個Waiter的動态代理的練習,這篇繼續來寫一個練習,一個動态代理工廠的例子,這個例子在以後學習Spring的時候會有幫助。這個動态工廠的主要作用就是包裝了下目标對象和前置增強和後置增強。

工廠類的使用步驟
我們要設計一個動态代理工廠類,以下是使用這個工程類的步驟。
來源:凱哥Java(kaigejava)
1. 建立代理工廠
2. 給工廠設定三樣東西
1) 目标對象,調用方法setTargetObject()
2) 前置增強,調用setBeforeAdvice(該接口的具體實作)
3) 後置增強,調用setAfterAdvice(該接口的具體實作)
3. 調用createProxy方法得到代理對象
執行代理對象方法時,按照以下順序執行。
1) 執行BeforeAdvice的before方法
2) 執行目标對象的目标方法
3) 執行AfterAdvice的after方法
前提準備
建立一個包,把前面的Waiter.java 和ManWaiter.java拷貝過來。
建立動态代理工廠類
這裡我們的代理工廠類,先給出目标對象,前置增強和後置增強,然後建立set和get方法。
下面是前置增強接口代碼
package demo1;
/**
* 前置增強
* @author anthony
*
*/
public interface BeforeAdvice {
public void before();
}
下面是後置增強接口代碼
package demo1;
/**
* 後置增強
* @author anthony
*
*/
public interface AfterAdvice {
public void after();
}
這裡面,我們暫時不知道程式員會在前置增強和後置增強寫什麼具體代碼,是以這裡我們利用接口來實作,程式員到時候寫代碼的時候,前置增強必須要實作前置增強接口中的before方法,後置增強必須實作後置增強接口中的after方法。
下面是代理工廠類的代碼
package demo1;
/**
* 這個類用來生成代理對象
* 需要所有參數
* *目标對象
* *增強
* @author anthony
*
*/
public class ProxyFactory {
private Object targetObject; // 目标對象
private BeforeAdvice beforeAdvice; // 前置增強
private AfterAdvice afterAdvice; // 後置增強
public Object getTargetObject() {
return targetObject;
}
public void setTargetObject(Object targetObject) {
this.targetObject = targetObject;
}
public BeforeAdvice getBeforeAdvice() {
return beforeAdvice;
}
public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
this.beforeAdvice = beforeAdvice;
}
public AfterAdvice getAfterAdvice() {
return afterAdvice;
}
public void setAfterAdvice(AfterAdvice afterAdvice) {
this.afterAdvice = afterAdvice;
}
}
這裡三個對象都給生成set和get方法,友善調用。
建立代理對象
前面代碼都不是重點,我們代理工廠重點部分來了,就是如何建立代理對象。這部分是在工廠類中,實作createProxy()方法,是本篇的重點内容,代碼如下。
package demo1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.omg.CORBA.portable.InvokeHandler;
/**
* 這個類用來生成代理對象
* 需要所有參數
* *目标對象
* *增強
* @author anthony
*
*/
public class ProxyFactory {
private Object targetObject; // 目标對象
private BeforeAdvice beforeAdvice; // 前置增強
private AfterAdvice afterAdvice; // 後置增強
/**
* 生成代理對象
* @return
*/
public Object createProxy() {
// 1. 給出三大參數
ClassLoader loader = this.getClass().getClassLoader();
Class[] interfaces = targetObject.getClass().getInterfaces();
InvocationHandler h = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 執行前置增強
if(beforeAdvice != null) {
beforeAdvice.before();
}
// 執行目标對象目标方法
Object result = method.invoke(targetObject, args);
// 執行後置增強
if(afterAdvice != null) {
afterAdvice.after();
}
return result;
}
};
// 2. 得到代理對象
Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
return proxyObject;
}
public Object getTargetObject() {
return targetObject;
}
public void setTargetObject(Object targetObject) {
this.targetObject = targetObject;
}
public BeforeAdvice getBeforeAdvice() {
return beforeAdvice;
}
public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
this.beforeAdvice = beforeAdvice;
}
public AfterAdvice getAfterAdvice() {
return afterAdvice;
}
public void setAfterAdvice(AfterAdvice afterAdvice) {
this.afterAdvice = afterAdvice;
}
}
上面代碼就是在createProxy()方法的時候,把目标對象和增強給做了以下組裝。接下來,看看如何代碼使用這個工廠類。
測試工廠類的使用
建立一個Demo1.java檔案,寫代碼來使用ProxyFactory這個動态代理工廠類。
package demo1;
import org.junit.Test;
public class Demo1 {
@Test
public void fun1() {
// 1. 建立工廠類對象
ProxyFactory factory = new ProxyFactory();
// 2.設定目标對象
factory.setTargetObject(new ManWaiter());
// 3.設定前置增強
factory.setBeforeAdvice(new BeforeAdvice() {
public void before() {
System.out.println("你好,歡迎光臨!");
}
});
// 4.設定後置增強
factory.setAfterAdvice(new AfterAdvice() {
public void after() {
System.out.println("再見,歡迎下次再來!");
}
});
// 5. 擷取代理對象, 執行增強代碼
Waiter waiter = (Waiter)factory.createProxy();
waiter.serve();
}
}
運作單元測試,得到如下輸出。
你好,歡迎光臨!
服務中...
再見,歡迎下次再來!
原創聲明,本文系作者授權騰訊雲開發者社群發表,未經許可,不得轉載。如有侵權,請聯系 [email protected] 删除。