- 代理模式
- 代理实现方式
- JDK动态代理实现
给某对象提供一个代理对象,通过代理对象可以访问该对象的功能。主要解决通过代理去访问[不能直接访问的对象],例如 租房中介,你可以直接通过中介去了解房东的房源信息,此时中介就可以称为代理。或者通过代理对象对原对象方法增强。
优点:
职责清晰、高扩展性、智能化
缺点
- 由于在客户端和真实subject之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
-
基于接口的动态代理
JDK官方提供的Proxy类
要求是被代理类最少实现一个接口
-
基于子类的动态代理
第三方的CGLib
要求是被代理类不能用final修饰的类(终类)即被代理的类要求可以作为父类被继承
代理模式不是说非要使用这些技术才能叫做代理模式,代理模式是一种设计模式的思想
JDK动态代理实现核心
- 被代理对象需要实现一个接口
- 代理对象需要实现 InvocationHandler 接口,重写invoke方法
代理访问被代理对象的指定方法,实现不直接调用被代理对象执行其方法,或者执行其增强方法而不同修改被代理对象方法代码
原理
给被代理对象实现的接口创建新的实现类(代理类)
// 被代理类实现的接口
public interface Landlord {
void rent(String name);
}
// 被代理实现类
public class LandlordImpl implements Landlord{
@Override
public void rent(String name) {
System.out.println(name + "房东把房子租给了他!");
}
}
// 代理类
public class Intermediary implements InvocationHandler {
private final Object instance;
public Intermediary(Object instance) {
this.instance = instance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在这里可以添加方法执行前的增强代码
System.out.println("代理前执行");
args[0] = args[0]+ "找到了中介, 中介帮他找到了合适的房东...";
Object result = method.invoke(instance, args);
// 在这里可以添加方法执行后的增强代码,但是不能添加输出语句
System.out.println("代理后执行");
return result;
}
}
这里invoke方法中有一个proxy参数
-
按理来讲invoke第一个参数是哪一个实例调用此方法,为什么不是this?
-
这个proxy参数在这里有什么用?
首先为什么不是this,这里的proxy表示的是实际调用被代理对象方法的代理实例,而在这个类中的this表示的是当前实例,这两个是不同的。
前者是Proxy.newProxyInstance()创建出来的代理对象,后者是辅助前者创建代理对象的实例,是InvocationHandler类型的(是个中介)。
就相当于房东把自己实例告诉中介,中介(this)稍作修饰后保存好,等需要的时候直接用中介保存好的版本(proxy)直接调用里面的方法
其次这个proxy在这里有什么作用?
-
可以通过反射获取到代理对象的一些信息
-
可以作为返回值返回,方便接收后继续链式调用
参考:添加链接描述
// 动态代理实现
// 1. 首先要有被代理对象的实例
Landlord landlord = new LandlordImpl();
// 2. 创建代理对象实例,但是代理对象不能直接new创建,通过Proxy类创建
Landlord landlordProxy = (Landlord) Proxy.newProxyInstance(
// 1. 被代理对象的类加载器(需要反射调用其方法)
landlord.getClass().getClassLoader(),
// 2. 被代理对象实现的所有接口,需要利用其接口创建新的代理实例
landlord.getClass().getInterfaces(),
// 3. 代理类型实例,需要实现InvocationHandler接口
new Intermediary(landlord)
);
// 调用通过被代理对象所有接口重新创建的新的代理对象的增强方法
landlordProxy.rent("张三");



