先来总结分析下代理模式。
动态代理需要的元素:
1.本身的逻辑接口;
2.代理逻辑部分(实现InvocationHandler接口);
客户端:
1.创建本地逻辑的接口的实例。
2.创建InvocationHandler接口的实例。
3.调用java.lang.reflect.Proxy#newProxyInstance生成代理类。
4.调用代理类相应的方法运行。
动态:代理类对应的class类在运行期生成。
限制:本地逻辑必须面向接口。
代码:
抽象接口的类图如下:
--图来自设计模式之禅
所以动态代理模式要有一个InvocationHandler接口 和 GamePlayerIH实现类。其中 InvocationHandler是JD提供的动态代理接口,对被代理类的方法进行代理。
代码实现如下
抽象主题类或者接口:
1 package com.yemaozi.proxy.dynamic; 2 3 /* 4 * 动态代理:就是实现阶段不用关系代理是哪个,而在运行阶段指定具体哪个代理。 5 */ 6 public interface IGamePlayer { 7 //登录游戏 8 public void login(String username, String password); 9 10 //击杀Boss 11 public void killBoss(); 12 13 //升级 14 public void upGrade(); 15 }
需要被代理类:
1 package com.yemaozi.proxy.dynamic; 2 3 public class GamePlayer implements IGamePlayer { 4 5 private String name = ""; 6 7 public GamePlayer(String name){ 8 this.name = name; 9 } 10 11 public void login(String username, String password) { 12 System.out.println("登录名为 "+username+" 进入游戏," + name + " 登录成功!"); 13 } 14 15 public void killBoss() { 16 System.out.println(this.name + " 击杀了Boss!"); 17 } 18 19 public void upGrade() { 20 System.out.println(this.name + "升级了!"); 21 } 22 23 }
动态代理处理器类:
1 package com.yemaozi.proxy.dynamic; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class GamePlayerInvocationHandler implements InvocationHandler{ 7 8 //被代理的对象 9 private Object obj; 10 11 //将需要代理的实例通过处理器类的构造方法传递给代理。 12 public GamePlayerInvocationHandler(Object obj){ 13 this.obj = obj; 14 } 15 16 public Object invoke(Object proxy, Method method, Object[] args) 17 throws Throwable { 18 Object result = null; 19 if("login".equalsIgnoreCase(method.getName())){ 20 //这个在主题方法不受任何影响的情况下,在主题方法前后添加新的功能,或者增强主题方法, 21 //从侧面切入从而达到扩展的效果的编程,就是面向切面编程(AOP Aspect Oriented Programming)。 22 //AOP并不是新技术,而是相对于面向对象编程的一种新的编程思想。在日志,事务,权限等方面使用较多。 23 System.out.println("代理登录游戏!"); 24 result = method.invoke(this.obj, args); 25 return result; 26 } 27 result = method.invoke(this.obj, args); 28 return result; 29 } 30 31 }
由于代理是动态产生的,所以不需要再声明代理类。
动态代理场景类:
package com.yemaozi.proxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { IGamePlayer gp = new GamePlayer("张三"); InvocationHandler gpHandler = new GamePlayerInvocationHandler(gp); //获取真实主题类的ClassLoader ClassLoader classLoader = gp.getClass().getClassLoader(); //动态产生一个代理者。 Class<?>[] cls = new Class[]{IGamePlayer.class}; IGamePlayer proxyGp = (IGamePlayer) Proxy.newProxyInstance(classLoader, cls, gpHandler); proxyGp.login("zhangsan", "123456"); proxyGp.killBoss(); proxyGp.upGrade(); } } 执行结果: 代理登录游戏! 登录名为 zhangsan 进入游戏,张三 登录成功! 张三 击杀了Boss! 张三升级了! //在此,我们没有创建代理类,但是确实有代理类帮我们完成事情。