Java面试-动态代理

2021-04-12 21:27

阅读:346

标签:cglib   jvm   ted   jdk动态代理   程序   引擎   tin   eth   private   

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

Java面试-动态代理

标签:cglib   jvm   ted   jdk动态代理   程序   引擎   tin   eth   private   

原文地址:https://www.cnblogs.com/moxie-/p/13347951.html


评论


亲,登录后才可以留言!