代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的访问。
- 静态代理模式
一个购票的场景:首先定义一个购票接口,该接口只有一个订票的方法。
public interface Bookingoffice {
void booking();
}
人如果要购票必需实现这个接口:
public class People implements Bookingoffice{
private String name;
private String phone;
public People(String name,String phone){
this.name = name;
this.phone = phone;
}
/**
* 购票方法
*/
public void booking() {
System.out.println(this.name+"购票");
}
}
现在人可以自己进行购票了, People people = new People(“Li “, “1886699112”),调用booking方法即可完成购票。但是有这种可能,人离车站比较远,不方便购票,此时就需要一个代理,帮助这个人购票。
定义一个代售点的类实现购票功能,并且需要手续中间费用:
/**
*
* @ClassName: Agency
* @Description:代售点
* @author li_bqian
* @date 2016年1月5日 下午2:26:34
*
*/
public class Agency implements Bookingoffice{
private Bookingoffice people;
public Agency(Bookingoffice people){
this.people = people;
}
@Override
public void booking() {
System.out.println("收取代理费用");
people.booking();
System.out.println("把票送到手中");
}
}
测试方法:
public static void main(String[] args) {
//构造一个人
People people = new People("Li ", "1886699112");
//代理点
Bookingoffice bookingoffice = new Agency(people);
//购票
bookingoffice.booking();
}
运行结果:
收取代理费用
Li 购票
把票送到手中
这样便完成了通过代理购票的功能。
现在有一个问题,如果有另一个接口也需要Agency 进行代理,使用静态代理的话只能新建另一个代理Agency2,而且Agency2中除了绑定的接口不一样外,其它代码都相同,造成代码的重复。解决办法就是将
Agency 绑定的被代理的对象设置成object类型,利用jdk反射机制实现代码的复用,这便是JDK动态代理。
JDK动态代理
首先定义一个MyInvocationHandler类继承InvocationHandler,该类主要构造代理要执行的操作,相当于生成代理对象的模板。
public class MyInvocationHandler implements InvocationHandler{
private Object target;//被代理的目标对象
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
/**
* 代理执行的方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 执行目标对象方法前的操作
System.out.println("-----------------before-----------------");
// 执行目标对象的方法
Object result = method.invoke(target, args);
// 在目标对象的方法后的操作
System.out.println("-------------------after------------------");
return result;
}
}
测试方法:
public static void main(String[] args) {
People people = new People("li","1562636622");
MyInvocationHandler invocationHandler = new MyInvocationHandler(people);
//获取代理对象
Object object = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
people.getClass().getInterfaces(), invocationHandler);
Bookingoffice booking =(Bookingoffice)object;
booking.booking();
}
Proxy.newProxyInstance三个参数:
paramClassLoader:类加载器,默认AppClassLoader
paramArrayOfClass:目标对象实现的接口
paramInvocationHandler:自定义的InvocationHandler
Cglib代理
使用jdk动态代理被代理的对象必须继承接口。如果没有继承接口,则使用Cglib进行处理。
定义一个类(被代理的目标对象),不继承任何接口:
public class Bookingoffice {
public void booking(){
System.out.println("购票");
}
}
定义生成代理对象的模板类继承MethodInterceptor:
public class BookofficeProxy implements MethodInterceptor{
private Object target;
/**
*
* @Title: getInstance
* @Description: 获取代理对象
* @param @param target
* @param @return 设定文件
* @return Object 返回类型
* @throws
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println("------before-----");
arg3.invokeSuper(arg0, arg2);
System.out.println("-----after-----");
return null;
}
}
测试方法:
public static void main(String[] args) {
Bookingoffice bookingoffice = new Bookingoffice();
BookofficeProxy bookofficeProxy = new BookofficeProxy();
Bookingoffice bookingcglib = (Bookingoffice) bookofficeProxy.getInstance(bookingoffice);
bookingcglib.booking();
}
执行结果:
------before-----
购票
-----after-----