一、引言
在 Spring
中,最重要的应该当属 IOC
和 AOP
了,IOC
的源码流程还比较简单,但 AOP
的流程就较为抽象了。
其中,AOP
中代理模式的重要性不言而喻,但对于没了解过代理模式的人来说,痛苦至极
于是,我就去看了动态代理的实现,发现网上大多数文章讲的都是不清不楚,甚至讲了和没讲似的,让我极其难受
本着咱们方向主打的就是源码,直接从从源码角度讲述一下 代理模式
兄弟们系好安全带,准备发车!
注意:本文篇幅较长,请留出较长时间来阅读
二、定义
代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
举个生活中常见的例子:客户想买房,房东有很多房,提供卖房服务,但房东不会带客户看房,于是客户通过中介买房。
这时候对于房东来说,不直接和客户沟通,而是交于中介进行代理
对于中介来说,她也会在原有的基础上收取一定的中介费
三、静态代理
我们创建 Landlord
接口如下:
public interface Landlord {
// 出租房子
void apartmentToRent();
}
复制代码
创建其实现类 HangZhouLandlord
代表杭州房东出租房子
public class HangZhouLandlord implements Landlord {
@Override
public void apartmentToRent() {
System.out.println("杭州房东出租房子");
}
}
复制代码
创建代理类 LandlordProxy
,代表中介服务
public class LandlordProxy {
public Landlord landlord;
public LandlordProxy(Landlord landlord) {
this.landlord = landlord;
}
public void apartmentToRent() {
apartmentToRentBefore();
landlord.apartmentToRent();
apartmentToRentAfter();
}
public void apartmentToRentBefore() {
System.out.println("出租房前,收取中介费");
}
public void apartmentToRentAfter() {
System.out.println("出租房后,签订合同");
}
}
复制代码
创建最终测试:
public class JavaMain {
public static void main(String[] args) {
Landlord landlord = new HangZhouLandlord();
LandlordProxy proxy = new LandlordProxy(landlord);
// 从中介进行租房
proxy.apartmentToRent();
}
}
复制代码
得出最终结果:
出租房前,收取中介费
杭州房东出租房子
出租房后,签订合同
复制代码
通过上述 demo
我们大概了解代理模式是怎么一回事
- 优点:
- 在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
- 缺点:
- 代理对象需要与目标对象实现一样的接口,所以会有很多代理类,一旦接口增加方法,目标对象与代理对象都要维护
四、动态代理
动态代理利用了JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能,动态代理又被称为JDK代理或接口代理。
静态代理与动态代理的区别:
- 静态代理在编译时就已经实现了,编译完成后代理类是一个实际的
class
文件 - 动态代理是在运行时动态生成的,即编译完成后没有实际的
class
文件,而是在运行时动态生成类字节码,并加载到JVM
中
1、JDK代理
代码如下:
public class ProxyFactory {
// 目标方法
public Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(
// 目标对象的类加载器
target.getClass().getClassLoader(),
// 目标对象的接口类型
target.getClass().getInterfaces(),
// 事件处理器
new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 代理对象调用的方法
* @param args 代理对象调用方法时实际的参数
* @return
* @throws T