天天看點

動态代理模式(抽象角色用接口形式,代理角色必須實作InvocationHandler)

動态代理

    接口UserManager

1. /***
2.  * 使用者控制接口
3.  * @author Administrator
4.  *
5.  */  
6. public interface UserManager {  
7.   
8. public void addUser(String userId,String userName);  
9. public void modifyUser(String userId,String userName);  
10. public void delUser(String userId);  
11. public String findUser(String userId);  
12. }      

    實作類UserManagerImpl

1. /****
2.  * 使用者管理真正的實作類
3.  * @author Administrator
4.  *
5.  */  
6. public class UserManagerImpl implements UserManager {  
7.   
8. /*****
9.      * 添加使用者
10.      */  
11. public void addUser(String userId, String userName) {  
12. "正在添加使用者,使用者為:"+userId+userName+"……");  
13.     }  
14. /*****
15.      * 删除使用者
16.      */  
17. public void delUser(String userId) {  
18. "delUser,userId="+userId);  
19.     }  
20. /***
21.      * 查找使用者
22.      */  
23. public String findUser(String userId) {  
24. "findUser,userId="+userId);  
25. return userId;  
26.     }  
27.   
28. public void modifyUser(String userId, String userName) {  
29. "modifyUser,userId="+userId);  
30.     }  
31. }      
1. import java.lang.reflect.InvocationHandler;  
2. import java.lang.reflect.Method;  
3. import java.lang.reflect.Proxy;  
4.   
5. public class LogHandler implements InvocationHandler {  
6.       
7. private Object targetObject;  
8.       
9. public Object newProxyInstance(Object targetObject) {  
10. this.targetObject = targetObject;  
11. return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
12. this);  
13.     }  
14.       
15. public Object invoke(Object proxy, Method method, Object[] args)  
16. throws Throwable {  
17. null;  
18.               
19. try {  
20. "正在進行操作前的準備工作……");  
21. //調用目标方法  
22.             ret = method.invoke(targetObject, args);  
23. "操作成功,正在進行确認處理……");  
24. catch (Exception e) {  
25.             e.printStackTrace();  
26. "error-->>" + method.getName());  
27. throw e;  
28.         }  
29. return ret;  
30.     }  
31. }      

    用戶端Client

1. public class Client {  
2.   
3. /**
4.      * @param args
5.      */  
6. public static void main(String[] args) {  
7. new LogHandler();  
8. new UserManagerImpl());  
9. "0001");  
10.     }  
11. }      

    運作結果

動态代理模式(抽象角色用接口形式,代理角色必須實作InvocationHandler)

    時序圖

動态代理模式(抽象角色用接口形式,代理角色必須實作InvocationHandler)

總結

    動态代理模式通過使用反射,可以在運作期決定加載哪個類,避免了一個類對應一個代理的問題;同時,通過統一的invoke方法,統一了代理類對原函數的處理過程,使用動态代理很大程度上減少了重複的代碼,降低了維護的複雜性和成本。

//**********************************************
 
接口
 
package com.ygl.dynamicproxy;
 public interface Subject {
    public void request();
 } 
//*********************
 
package com.ygl.dynamicproxy;


 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 /**
  * 該代理類的内部屬性是Object類型,實際使用時通過該類的構造方法傳遞進來一個對象
  * 此外,該類還重寫了invoke方法,該方法中的method。invoke其實就是被代理對象(真實對象)的将要執行的方法,
  * 方法參數subject表示該方法屬于subject對象,通過動态代理類,我們可以在執行真實對象的方法前後加入自己的方法
  * @author lenovo
  *
  */
 public class DynamicSubject implements InvocationHandler{
     private Object subject;
     
     public DynamicSubject(Object obj){
     this.subject=obj;
     }
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("bfore calling"+method);

method.invoke(subject, args);

System.out.println("after calling"+method);

return null;
}

 } 
//**************************************
 
package com.ygl.dynamicproxy;

 public class RealSubject implements Subject {

@Override
public void request() {
System.out.println("RealSubject");

}
 } 
//********************************
 
package com.ygl.dynamicproxy;


 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;


 public class Client {
 public static void main(String[] args) {

RealSubject  realSubject=new RealSubject();

InvocationHandler  handler=new DynamicSubject(realSubject);

Class<?>   clazz=handler.getClass();

System.out.println(clazz);
//下面的代碼一次性生成代理
//傳入真實角色實作的接口 realSubject.getClass().getInterfaces(),得到的subject是一個代理的執行個體class $Proxy0其實作了 realSubject.getClass().getInterfaces()這些接口
Subject subject=(Subject)Proxy.newProxyInstance(clazz.getClassLoader(), realSubject.getClass().getInterfaces(), handler);
System.out.println(subject.getClass());//class $Proxy0 
subject.request();//此時會執行相應handler裡的invoke方法

 }
 } 
//*******************
 
class com.ygl.dynamicproxy.DynamicSubject
 bfore callingpublic abstract void com.ygl.dynamicproxy.Subject.request()
 RealSubject
 after callingpublic abstract void com.ygl.dynamicproxy.Subject.request()
 class $Proxy0