代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
1、静态代理
静态代理:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。
静态代理通常用于对原有业务逻辑的扩充。比如持有二方包的某个类,并调用了其中的某些方法。然后出于某种原因,比如记录日志、打印方法执行时间,但是又不好将这些逻辑写入二方包的方法里。所以可以创建一个代理类实现和二方方法相同的方法,通过让代理类持有真实对象,然后在原代码中调用代理类方法,来达到添加我们需要业务逻辑的目的。
这其实也就是代理模式的一种实现,通过对真实对象的封装,来实现扩展性。
一个典型的代理模式通常有三个角色,这里称之为**代理三要素**
共同接口
package com.ken.staticproxy; public interface Person { void giveMoney(); }
真实对象
package com.ken.staticproxy; public class Student implements Person { private String name; public Student(String name) { this.name = name; } @Override public void giveMoney() { // TODO Auto-generated method stub System.out.println(name + "上交班费50元"); } }
代理对象
package com.ken.staticproxy; public class StudentProxy implements Person { Student stu; public StudentProxy(Person stu) { // 只代理学生对象 if(stu.getClass() == Student.class) { this.stu = (Student)stu; } } @Override public void giveMoney() { // TODO Auto-generated method stub System.out.println("this is proxy start!"); stu.giveMoney(); System.out.println("this is proxy end!"); } }
测试
package com.ken.staticproxy; public class Test { public static void main(String[] args) { Person person = new Student("test"); person.giveMoney(); System.out.println("-------------------------"); Person proxy = new StudentProxy(person); proxy.giveMoney(); } }
输出结果
test上交班费50元 ------------------------- this is proxy start! test上交班费50元 this is proxy end!
静态代理的优点和缺点
先看看代理模式的优点: 扩展原功能,不侵入原代码。
再看看这种代理模式的缺点:如果需要扩展的扩展的功能模块太多则需要增加更多的方法
2、动态代理
代理类在程序运行时创建的代理方式被成为动态代理。 我们上面静态代理的例子中,代理类(studentProxy)是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。 比如说,想要在每个代理的方法前都加上一个处理方法:
动态代理实现
使用动态代理,需要将要扩展的功能写在一个InvocationHandler 实现类里:
这个Handler中的invoke方法中实现了代理类要扩展的公共功能。
public class StudentProxy implements InvocationHandler{ private Object realObject; public StudentProxy(Object realObject) { this.realObject = realObject; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //代理扩展逻辑 System.out.println("this is proxy start!"); Object object = method.invoke(realObject, args); System.out.println("this is proxy end!"); return object; } }
测试
Proxy.newProxyInstance 传入的是一个ClassLoader, 一个代理接口,和我们定义的handler,返回的是一个Proxy的实例。
import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { Person person = new Student("test"); person.giveMoney(); System.out.println("-------------------------"); Person proxy = (Person) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Person.class}, new StudentProxy(person)); proxy.giveMoney(); } }
输出结果
test上交班费50元 ------------------------- this is proxy start! test上交班费50元 this is proxy end!