前面我们学习了 Spring AOP
的应用,接下来我们看看 Spring
是如何实现 AOP
的
Spring AOP
是基于动态代理来实现 AOP
的,我们主要学习:
Spring AOP
源码剖析代理模式,也叫委托模式
定义:为其他对象提供一种代理以控制对这个对象的访问。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用
在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
使用代理前:
使用代理后:
生活中的代理
代理模式的主要角色
Subject
:业务接口类。可以是抽象类或者接口(不一定有)RealSubject
:业务实现类。具体的业务执行,也就是被代理对象Proxy
:代理类。RealSubject
的代理比如房屋租赁
Subject
就是提前定义了房东做的事情,交给中介代理,也是中介要做的事情RealSubject
:房东Proxy
:中介UML
类图如下:
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强
根据代理的创建时期,代理模式分为静态代理和动态代理
.class
文件就已经存在了 静态代理:在程序运行前,代理类的 .class
文件就已经存在了(在出租房子前,中介已经做好了相关的工作,就等租户来租房子了)
我们通过代码来加深理解。以房屋租赁为例
我们通过代码来加深理解。以房屋租赁为例
public interface HouseSubject {
void rentHouse();
}
public class RealHouseSubject implements HouseSubject{
@Override
public void rentHouse() {
System.out.println("我是房东,我出租房子!");
}
}
public class HouseProxy implements HouseSubject{
// 将被代理对象声明为成员变量
private HouseSubject houseSubject;
public HouseProxy(HouseSubject houseSubject) {
this.houseSubject = houseSubject;
}
@Override
public void rentHouse() {
// 开始代理
System.out.println("我是中介,开始代理");
// 代理房东出租房子
houseSubject.rentHouse();
// 代理结束
System.out.println("我是中介,代理结束");
}
}
public class StaticMain {
public static void main(String[] args) {
HouseSubject subject = new RealHouseSubject();
// 创建代理类
HouseProxy proxy = new HouseProxy(subject);
// 通过代理类访问目标方法
proxy.rentHouse();
}
}
运行结果:
上面这个代理实现方式就是静态代理(仿佛什么也没干)
从上述程序可以看出,虽然静态代理也完成了对目标对象的代理,但是由于代码都写死了,对目标对象的每个方法的增强都是手动完成的,非常不灵活。所以日常开发几乎看不到静态代理的场景
接下来新增需求:中介又新增了其他业务:代理房屋出售
public interface HouseSubject {
void rentHouse();
void saleHouse();
}
public class RealHouseSubject implements HouseSubject{
@Override
public void rentHouse() {
System.out.println("我是房东,我出租房子!");
}
@Override
public void saleHouse() {
System.out.println("我是房东,我要出售房子");
}
}
public class HouseProxy implements HouseSubject{
// 将被代理对象声明为成员变量
private HouseSubject houseSubject;
public HouseProxy(HouseSubject houseSubject) {
this.houseSubject = houseSubject;
}
@Override
public void rentHouse() {
// 开始代理
System.out.println("我是中介,开始代理");
// 代理房东出租房子
houseSubject.rentHouse();
// 代理结束
System.out.println("我是中介,代理结束");
}
@Override
public void saleHouse() {
// 开始代理
System.out.println("我是中介,开始代理");
// 代理房东出租房子
houseSubject.saleHouse();
// 代理结束
System.out.println("我是中介,代理结束");
}
}
从上述代码可以看出,我们修改接口(Subject
)和业务实现类(RealSubject
)时,还需要修改代理类(Proxy
)
同样的,如果有新增接口(Subject
)和业务实现类(RealSubject
),也需要对每一个业务实现类新增代理类(Proxy
)
既然代理的流程是一样的,有没有一种办法,让他们能通过一个代理类来实现呢?