Java面试-动态代理
Posted Moxie一直在奋斗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
以上是关于Java面试-动态代理的主要内容,如果未能解决你的问题,请参考以下文章