探討代理模式與Java反射機制的應用
代理模式,相信大多數人都非常熟悉,常見的實現方式是通過公共介面的方式,讓我們的目標類和代理類實現同一介面,在代理類中呼叫目標類物件的方法。通過介面的方式,有個不好的地方,就是對每個目標類都要寫一對與之相對應的介面和代理類,如果業務類很多,就是非常繁鎖的工作了。
而加入反射機制的代理模式,可實現一個公共的代理類,省去我們不少功夫。Java的java.lang.reflect包及其子包中提供了Class、Method、Annotation等有用的類。下面,寫個方法代理的類MethodProxy,實現動態地呼叫物件的方法。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 方法代理類
* @author rongxinhua
*
*/
public class MethodProxy {
private Class clazz; //物件所屬的類
private Object target; //目標物件
private Method method; //目標方法
private Object[] params; //引數陣列
@SuppressWarnings("unchecked")
public MethodProxy(Object target, String methodName, Object ... params) {
rebindTarget(target, methodName, params); //設定目標物件與方法
}
/**
* 重新設定目標物件與方法
* @param target
* @param methodName
* @param params
*/
public void rebindTarget(Object target, String methodName, Object ... params) {
this.target = target;
this.clazz = target.getClass();
rebindMethod(methodName, params); //設定目標方法
}
/**
* 重新設定目標方法
* @param methodName
* @param params
*/
public void rebindMethod(String methodName, Object ...params) {
this.params = params;
int paramLength = params.length;
Class[] paramTypes = new Class[paramLength];
for(int i = 0 ; i < paramLength ; i ++ ) {
paramTypes[i] = params[i].getClass();
}
try {
this.method = clazz.getMethod(methodName, paramTypes);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
/**
* 動態呼叫已繫結的方法
*/
public void doMethod() {
try {
this.method.invoke(target, params);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
這樣就可以實現動態地呼叫某個物件的某個方法了,寫個測試程式碼如下:
public class Manager {
public void say() {
System.out.println("Nobody say nothing");
}
public void love(String boy, String girl) {
System.out.println(boy + " love " + girl);
}
}
我們通過代理類來呼叫Manager類中的say()和love()方法,測試程式碼如下:
Manager man = new Manager(); //目標物件
MethodProxy proxy = new MethodProxy(man, "say"); //方法代理物件
proxy.doMethod(); //呼叫被代理的方法
proxy.rebindMethod("love", "Tom", "Marry"); //重新繫結方法
proxy.doMethod(); //呼叫被代理的方法
這樣就實現了動態代理呼叫物件的方法,上面程式碼輸出結果就不貼出來了。如果要設定前置通知和後置通知等功能,也很容易實現,只需在“proxy.doMethod()”程式碼處的前面和後面設定即行。
擴充套件應用:我們在上面的MethodProxy類中加入以下方法:
/**
* 獲取方法上的註解
* @param anClazz 註解類
* @return
*/
public Annotation getAnnotation(Class anClazz) {
return this.method.getAnnotation(anClazz);
}
這個方法用來讀取方法上的註解(Annotation),有什麼用呢?我們寫一個註解來測試下。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Low {
int boyAge(); //男孩法定的談戀愛年齡
int girlAge(); //女孩法定的談戀愛年齡
}
我們要引進Annotation相關的類:
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
我們另外寫一個測試用的業務類:
public class LoveManager {
@Low(boyAge=12, girlAge=10)
public void beAbleToLove(Person boy, Person girl) {
System.out.println(boy.getName() + " is able to love " + girl.getName());
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//getter方法略
}
接寫上例中的proxy物件測試程式碼:
LoveManager loveManager = new LoveManager();
Person boy = new Person("Tom", 13);
Person girl = new Person("Marry", 10);
proxy.rebindTarget(loveManager, "beAbleToLove", boy, girl); //重新繫結物件和方法
Low low = (Low)proxy.getAnnotation(Low.class);
if(boy.getAge() < low.boyAge()) {
System.out.println(boy.getName() + "還不到法定年齡,不能談戀愛!");
} else if(girl.getAge() < low.girlAge()) {
System.out.println(girl.getName() + "還不到法定年齡,不能談戀愛!");
} else {
proxy.doMethod();
}
根據boy和girl的年齡大小,會相應地輸出下列之一:
Tom還不到法定年齡,不能談戀愛! Marry還不到法定年齡,不能談戀愛! Tom is able to love Marry
這就實現了,通過Java的反射來讀取Annotation的值,並根據Annotation的值,來處理業務資料有效性的判斷,或者面向切面動態地注入物件,或者作日誌、攔截器等等。這種用法在所多框架中都常常看到, 我們在開發自己的Java元件時,不妨也採用一下吧!
相關文章
- Java - 反射機制與工廠設計模式Java反射設計模式
- Java - 反射機制與單例設計模式Java反射單例設計模式
- Java動態代理和反射機制Java反射
- Sidecar 模式的機制與應用IDE模式
- 反射機制及應用反射
- 唯品會 JIT模式 應用探討模式
- Java註解與反射機制Java反射
- Java的反射機制Java反射
- Java反射機制Java反射
- Sql Server深入的探討鎖機制SQLServer
- Java 中的 反射機制Java反射
- oracle 雙機部署模式探討Oracle模式
- Java核心反射機制Java反射
- java利器——反射機制Java反射
- Java的代理機制Java
- Java中的類反射機制Java反射
- 反射和代理的具體應用反射
- Java進階 | 泛型機制與反射原理Java泛型反射
- 深入探討控制反轉(IOC)與依賴注入(DI)模式原理與應用實踐依賴注入模式
- 聽技術探討一對一原始碼與視訊聊天系統分銷代理機制!原始碼
- 小白都能學會的Java註解與反射機制Java反射
- Java反射機制簡答Java反射
- Java反射機制那些事Java反射
- Java代理機制分析——JDK代理(Proxy、InvocationHandler與示例)JavaJDK
- Java 反射機制的三種方式Java反射
- java反射機制的學習心得Java反射
- 關於Java中的反射機制Java反射
- java進階(41)--反射機制Java反射
- Java筆記-反射機制(一)Java筆記反射
- 淺談Java的反射機制和作用Java反射
- TRIZ理論在洗碗機設計中應用探討
- Java核心技術梳理-類載入機制與反射Java反射
- java基礎:深入理解Class物件與反射機制Java物件反射
- 類載入機制與反射反射
- JAVA-反射與工廠模式Java反射模式
- 深入探討單例模式單例模式
- Java基礎之反射機制(續)Java反射
- Java重點基礎:反射機制Java反射
- Web 框架的架構模式探討Web框架架構模式