一、代理模式简介
代理模式的作用是:为其他对象提供一种代理,以控制对这个对象的访问。在某种情况下,一个客户不想或者不能直接引用另一个对象,此时代理对象可以在客户端 和目标对象之间起到中介的作用。单例模式有如下特点:
- 职责清晰:真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
- 代理对象:可以在客户端和目标对象之前起到中介的作用,这样保护了目标对象
- 高扩展性
代理模式UML图如下:
二、代理模式实现
代理模式一般涉及到的角色如下:
- 抽象角色:声明真实对象和代理对象的共同接口
- 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装
- 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象
我们使用到JDK提供的代理类来实现动态代理。
1、创建Subject接口(抽象角色)
1 package com.test.dynamicproxy; 2 3 public interface Subject 4 { 5 public void request(); 6 }
2、创建RealSubject类(真实角色)
1 package com.test.dynamicproxy; 2 3 public class RealSubject implements Subject 4 { 5 public void request() 6 { 7 System.out.println("From real subject!"); 8 } 9 10 }
3、创建DynamicSubject(该类用于产生代理对象)
1 package com.test.dynamicproxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 /** 7 * 该代理类的内部属性是Object类型,实际使用的时候通过该类的构造方法传递进来一个对象 8 * 此外,该类还实现了invoke方法,该方法中的method.invoke其实就是调用被代理对象的将要 9 * 执行的方法,方法参数是sub,表示该方法从属于sub,通过动态代理类,我们可以在执行真实对象的方法前后 加入自己的一些额外方法。 10 * 11 */ 12 13 public class DynamicSubject implements InvocationHandler { 14 private Object sub; 15 16 public DynamicSubject(Object obj) { 17 this.sub = obj; 18 } 19 20 // 以下的参数由底层传递。。。 21 22 /** 23 *@param proxy 代理对象 24 * 25 *@param method 要代理的方法 26 * 27 *@param args 该方法的参数对象数组 28 * 29 *@return 30 */ 31 public Object invoke(Object proxy, Method method, Object[] args) 32 throws Throwable { 33 System.out.println("before calling: " + method); 34 35 method.invoke(sub, args);// 掉用真实对象的方法,通过反射来调用 36 37 System.out.println(args == null);//方法没有参数则为空 38 39 System.out.println("after calling: " + method); 40 41 return null; 42 } 43 44 }
4、调用类Client
1 package com.test.dynamicproxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Proxy; 5 6 public class Client { 7 public static void main(String[] args) { 8 // 创建真实对象 9 RealSubject realSubject = new RealSubject(); 10 11 // 设置要被代理的对象 12 InvocationHandler handler = new DynamicSubject(realSubject); 13 14 Class<?> classType = handler.getClass(); 15 16 // 下面的代码一次性生成代理对象 17 Subject subject = (Subject) Proxy.newProxyInstance(classType 18 .getClassLoader(), realSubject.getClass().getInterfaces(), 19 handler); 20 21 subject.request(); 22 23 System.out.println(subject.getClass()); 24 } 25 }
5、运行结果如下: