一、定义:
为其他对象提供一种代理以控制对这个对象的访问。
二、通用类图:
Subject抽象主题角色
通用代码:
public interface Subject { //定义一个方法 public void request(); }
RealSubject具体主题角色
通用代码:
public class RealSubject implements Subject { //实现方法 public void request() { //业务逻辑处理 } }
Proxy代理主题角色:负责对真是角色的应用,并做预处理和善后处理工作。
public class Proxy implements Subject { //要代理哪个实现类 private Subject subject = null; //默认被代理者 public Proxy(){ this.subject = new Proxy(); } //通过构造方法传递代理者 public Proxy(Object...objects ){ } //实现接口中定义方法 public void request() { this.before(); this.subject.request(); this.after(); } //预处理 private void before(){ //do something } //善后处理 private void after(){ //do something } }
在通常情况下,一个接口只需要一个代理类就可以了,具体代理哪个实现类由高层模块来决定。可以在代理类Proxy中增加构造函数:
public Proxy(Subject _subject){ this.subject = _subject; }
三、使用场景:
Spring AOP是一个非常典型的动态代理。
四、代理模式的扩展
1、普通代理
要求客户端只能访问代理角色,而不能访问真实角色
2、强制代理
强制代理的概念就是要从真实角色查找到代理角色
3、重点:动态代理
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。即动态产生代理类
Java动态代理类位于java.lang.reflect包下,涉及两个类:
(1)InvocationHandler事务处理器接口中定义方法
Object invoke (Object obj,Method method,Object[] args)
obj代理类,method是被代理的方法,args为方法参数数组。这个抽象方法在代理类中动态实现
(2)Proxy动态代理类
Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
返回代理类的一个实例,返回的代理类可以当做被代理类使用。
实现步骤:
(1)创建一个实现接口InvocationHandler的类,它必须实现invoke方法
(2)创建被代理的类以及接口
(3)调用Proxy的静态方法,创建一个代理类
(4)通过代理调用方法
下面以玩游戏为例,实现动态代理:
游戏玩儿家接口:
public interface IGamePlayer { //登录 public void login(String user,String password); //打怪 public void killBoss(); //升级 public void upgrade(); }
游戏玩儿家实现类:
public class GamePlayer implements IGamePlayer { private String name = ""; public GamePlayer(String name){ this.name = name; } public void killBoss() { System.out.println(this.name + "打怪"); } public void login(String user, String password) { System.out.println("登录名"+user+"的用户"+this.name+"登录成功"); } public void upgrade() { System.out.println(this.name + "升级了"); } }
事务处理器:
public class GamePlayIH implements InvocationHandler { //被代理者实例 Object obj = null; //构造函数 public GamePlayIH(Object obj){ this.obj = obj; } /** * /调用被代理的方法 * @param proxy 被代理的对象 * @param method 被代理对象的方法 * @param args 方法参数 * @return 方法返回值 * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始代理"); Object result = method.invoke(this.obj, args); System.out.println("结束代理"); return result; } }
场景类:
public class Client { public static void main(String[] args) throws Throwable { IGamePlayer player = new GamePlayer("wbao"); InvocationHandler handler = new GamePlayIH(player); ClassLoader cl = player.getClass().getClassLoader(); //动态产生一个代理者 IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl, player.getClass().getInterfaces(), handler); proxy.login("wbao", "password"); proxy.killBoss(); proxy.upgrade(); } }
程序执行结果:
开始代理
登录名wbao的用户wbao登录成功
结束代理
开始代理
wbao打怪
结束代理
开始代理
wbao升级了
结束代理
优化:简化场景类调用,增加通知Advice
类图: