Java面試-動態代理


1. 動態代理分類

動態代理的兩種實現方式:1)JDK動態代理;2)CGLIB動態代理

 

2. JDK動態代理Demo

JDK動態代理所用到的代理類在程序調用到代理類對象時才由JVM真正創建,JVM根據傳進來的 業務實現類對象 以及 方法名 ,動態地創建了一個代理類的class文件並被字節碼引擎執行,然后通過該代理類對象進行方法調用。我們需要做的,只需指定代理類的預處理、調用后操作即可。

1. 定義User接口

public interface User {
        
    public void login();
    public void logout();

}

 

2. 分別實現Student類和administrator類

 1 // Student類
 2 public class Student implements User {
 3     
 4     String Name;
 5     
 6     @Override
 7     public void login() {
 8         System.out.println("Student login!");        
 9     }
10 
11     @Override
12     public void logout() {
13         System.out.println("Student logout!");        
14     }
15 
16 }
17 
18 // administrator類
19 public class Administrator implements User{
20     
21     String Name;
22     
23     @Override
24     public void login() {
25         System.out.println("Administrator login!");        
26     }
27 
28     @Override
29     public void logout() {
30         System.out.println("Administrator logout!");        
31     }
32 
33 }

 

 3. 實現 調用管理接口InvocationHandler  創建動態代理類

 1 public class LoginProxy implements InvocationHandler {
 2     
 3     private Object user; // 業務實現類對象,用來調用具體的業務方法
 4 
 5 
 6         /** 
 7         *       包裝調用方法:進行預處理、調用后處理 
 8         */
 9     @Override
10     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
11         // TODO Auto-generated method stub
12         
13         //    根據傳入user所屬類為用戶分配權限
14         if(user.getClass() == Student.class) {
15             
16             System.out.println("獲取管理員權限失敗!");
17             
18         }else if(user.getClass() == Administrator.class) {
19                     
20             method.invoke(user, args);
21             
22         }else {
23             System.out.println("失敗!");
24         }
25     
26         return null;
27     }
28     
29         /** 
30     *     綁定業務對象並返回一個代理類  
31         */ 
32     public Object bind(Object user) {
33         
34         this.user = user; //接收業務實現類對象參數
35         
36                 //通過反射機制,創建一個代理類對象實例並返回。用戶進行方法調用時使用
37        //創建代理對象時,需要傳遞該業務類的類加載器(用來獲取業務實現類的元數據,在包裝方法是調用真正的業務方法)、接口、handler實現類
38         return Proxy.newProxyInstance(user.getClass().getClassLoader(), 
39                 user.getClass().getInterfaces(), this);
40         
41     }
42     
43     
44 }

 

4. 在使用時,首先創建一個業務實現類對象和一個代理類對象,然后定義接口引用(這里使用向上轉型)並用代理對象.bind(業務實現類對象)的返回值進行賦值。最后通過接口引用調用業務方法即可。(接口引用真正指向的是一個綁定了業務類的代理類對象,所以通過接口方法名調用的是被代理的方法們)

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        // student用戶
        User student = new Student();        
        LoginProxy handler = new LoginProxy();        
        User user = (User) handler.bind(student);        
        user.login();
        
        // admin用戶
        User admin = new Administrator();        
        LoginProxy handler2 = new LoginProxy();        
        User user2 = (User) handler2.bind(admin);        
        user2.login();
    }

}

 

5. 查看命令行輸出

1 獲取管理員權限失敗!
2 Administrator login!

 

JDK動態代理的代理對象在創建時,需要使用業務實現類所實現的接口作為參數(因為在后面代理方法時需要根據接口內的方法名進行調用)。如果業務實現類是沒有實現接口而是直接定義業務方法的話,就無法使用JDK動態代理了。並且,如果業務實現類中新增了接口中沒有的方法,這些方法是無法被代理的(因為無法被調用)。

 

3. CGLIB動態代理Demo

...先空着

 

4. 比較

 

    JDK動態代理是通過接口中的方法名,在動態生成的代理類中調用業務實現類的同名方法;

    CGlib動態代理是通過繼承業務類,生成的動態代理類是業務類的子類,通過重寫業務方法進行代理;

 

參考:https://www.cnblogs.com/ygj0930/p/6542259.html

     http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

          http://www.360doc.com/content/14/0801/14/1073512_398598312.shtml


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM