【JAVA】代理模式之Java動態代理
代理模式之Java動態代理
1. Overview
Java在java.lang.reflect包下,定義了自己的代理 。利用這個包下的類,我們可以在執行時動態地建立一個代理類,實現一個或多個介面 。並將方法的呼叫轉發到你所指定的類 。因為實際代理是在執行時建立的,所以稱為:動態代理 。
Proxy:完全由java產生的,而且實現了完整的subject介面 。
InvocationHandler:Proxy上的任何方法呼叫都會被傳入此類,InvocationHandler控制對RealSubject的訪問 。
因為Java已經幫助我們建立了Proxy類,我們需要有辦法告訴Proxy類你要做什麼,我們不能像以前一樣把程式碼寫入到Proxy類中,因為Proxy類不是我們實現的 。那麼我們應該放在哪裡?放在InvocationHandler類中,InvocationHandler類是響應代理的任何呼叫 。我們可以吧InvocationHandler想成是代理收到方法呼叫後,請求做實際工作的物件 。
2. java.lang.reflect.InvocationHandler
被代理例項所實現的一個介面,內部只有一個invoke()方法,簽名如下;
Java程式碼
public Object invoke(Object proxy, Method method, Object[] args)
當代理的方法被呼叫的時候,代理就會把這個呼叫轉發給InvocationHandler,也就會呼叫它的invoke()方法 。
3. java.lang.reflect.Proxy
提供用於建立動態代理類和例項的靜態方法,它還是由這些方法建立的所有動態代理類的超類,我們經常使用的靜態方式是:
Java程式碼
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
4. 示例:
情形:自己可以檢視修改姓名性別,但是不能修改rate 。他人可以檢視姓名,性別以及修改rate,但是不能修改姓名性別 。
4.1 定義一個介面:
Java程式碼
public interface Person {
String getName();
String getGender();
void setName(String name);
void setGender(String gender);
void setRate(int rate);
int getRate();
}
4.2 定義實現Person介面類
Java程式碼
public class PersonImpl implements Person { String name; String gender; String interests; int rate; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getInterests() { return interests; } public void setInterests(String interests) { this.interests = interests; } public int getRate() { return rate; } public void setRate(int rate) { this.rate = rate; }
4.3 定義OwnerInvocationHandler類,表示如果為本人,則可以進行修改檢視姓名性別 。
Java程式碼
public class OwnerInvocationHandler implements InvocationHandler{ private Person personBean; public OwnerInvocationHandler(Person personBean){ this.personBean = personBean; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { if(method.getName().startsWith("get")){//如果方法名為get,就呼叫person類內的get相應方法 return method.invoke(personBean, args); }else if(method.getName().equals("setRate")){ // 如果方法是setRate,則丟擲異常 throw new IllegalAccessException("access deny"); }else if(method.getName().startsWith("set")){ //如果為set,就呼叫person類內的set相應方法 return method.invoke(personBean, args); }else { System.out.println("non method invoke"); } } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } }
4.4 定義NonInvocationHandler類,表示如果不為本人,則可以進行檢視姓名性別和修改rate 。
Java程式碼
public class NonInvocationHandler implements InvocationHandler{ // private Person person; public NonInvocationHandler(Person person){ this.person = person; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().startsWith("setRate")){ return method.invoke(person, args); }else if (method.getName().startsWith("get")){ return method.invoke(person, args); } else { System.out.println("non method invoke"); return null; } } }
4.5 測試類MyDynamicProxy
Java程式碼
public class MyDynamicProxy { public Person getOwnerPersonBeanProxy(Person person){ return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new OwnerInvocationHandler(person)); } public Person getNonPersonBeanProxy(Person person){ return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new NonInvocationHandler(person)); } public static void main(String[] args) { MyDynamicProxy mdp = new MyDynamicProxy(); mdp.test(); } public void test(){ // Person person = getPersonBeanFromDB1(); Person personProxy = getOwnerPersonBeanProxy(person); System.out.println(personProxy.getName()); try { personProxy.setRate(2); } catch (Exception e) { System.out.println("can not setRate"); } // Person person1 = getPersonBeanFromDB1(); Person personProxy2 = getNonPersonBeanProxy(person1); System.out.println(personProxy2.getName()); personProxy2.setRate(2); System.out.println(personProxy2.getRate()); } private Person getPersonBeanFromDB1(){ Person pb = new PersonImpl(); pb.setName("remy"); pb.setGender("girl"); pb.setRate(1); return pb; }
輸出結果:
Java程式碼
remy can not setRate remy 2
相關文章
- Java設計模式-之代理模式(動態代理)Java設計模式
- Java Web之動態代理JavaWeb
- JAVA 靜態代理 & 動態代理Java
- Java代理之靜態代理Java
- java靜態代理和動態代理Java
- 設計模式總結——代理模式以及java的動態代理設計模式Java
- Java代理(jdk靜態代理、動態代理和cglib動態代理)JavaJDKCGLib
- Java靜態代理模式Java模式
- java動態代理Java
- Java進階之 JDK動態代理與Cglib動態代理JavaJDKCGLib
- Java設計模式學習06——靜態代理與動態代理Java設計模式
- Java類關係之代理(代理模式)Java模式
- 設計模式_JAVA動態代理設計模式設計模式Java
- 代理模式 - 動態代理模式
- 【菜鳥學Java】13:代理模式——動態代理這樣玩!Java模式
- Java動態代理(AOP)Java
- java動態代理(1)Java
- java 的動態代理Java
- Java Proxy動態代理Java
- java動態代理原理Java
- 輕鬆理解 Java 靜態代理/動態代理Java
- Java中的靜態代理和動態代理Java
- Java進階--Java動態代理Java
- (轉)Java動態代理與CGLib代理JavaCGLib
- Java設計模式之代理模式Java設計模式
- Java基礎之代理模式Java模式
- Java基礎系列-靜態代理和動態代理Java
- JAVA學習篇--靜態代理VS動態代理Java
- java動態代理動態在哪裡?Java
- Java代理設計模式(Proxy)的四種具體實現:靜態代理和動態代理Java設計模式
- Java架構-Java JDK 動態代理Java架構JDK
- Java 動態代理newProxyInstanceJava
- 動態代理及java演示Java
- java動態代理如何使用Java
- java 反射和動態代理Java反射
- Java 動態代理深入解析Java
- 代理模式詳解:靜態代理、JDK動態代理與Cglib動態代理模式JDKCGLib
- Java設計模式之(五)——代理模式Java設計模式