26. 什么是代理模式?Spring AOP使用哪种代理模式来实现AOP?
大约 4 分钟
代理模式(Proxy Pattern)是一种设计模式,它为其他对象提供一种代理,以控制对这个对象的访问。代理模式可以用于多种目的,比如延迟加载(懒加载)、访问控制、日志记录等。在这种模式中,代理对象代表另一个对象(即实际对象)来执行操作。
代理模式的核心思想是:
- 代理对象(Proxy):持有对实际对象的引用,并提供与实际对象相同的接口。代理对象在执行操作时,可以在调用实际对象的方法之前或之后添加额外的功能。
- 实际对象(Real Subject):执行具体操作的对象,代理对象最终会将调用委托给这个对象。
- 客户端(Client):通过代理对象来调用实际对象的方法,而无需直接与实际对象交互。
代理模式的示例
interface Service {
void request();
}
class RealService implements Service {
@Override
public void request() {
System.out.println("Executing request in RealService");
}
}
class ProxyService implements Service {
private RealService realService;
public ProxyService(RealService realService) {
this.realService = realService;
}
@Override
public void request() {
System.out.println("ProxyService: Logging before request");
realService.request(); // 调用实际对象的方法
System.out.println("ProxyService: Logging after request");
}
}
public class ProxyPatternExample {
public static void main(String[] args) {
RealService realService = new RealService();
Service proxyService = new ProxyService(realService);
proxyService.request(); // 通过代理对象调用方法
}
}
在这个示例中,ProxyService
是代理对象,RealService
是实际对象,proxyService
是客户端使用的对象。通过代理对象,客户端在执行操作时可以添加额外的逻辑,比如日志记录。
Spring AOP中的代理模式
Spring AOP 通过代理模式来实现面向切面编程(AOP)。在Spring AOP中,当你定义一个切面时,Spring会为目标对象创建一个代理对象。这个代理对象负责在调用目标方法前后执行切面逻辑(例如通知)。
Spring AOP 使用的代理模式类型
Spring AOP 支持两种代理模式:
基于接口的代理(JDK动态代理):
- Spring 使用 JDK 动态代理为实现了接口的目标对象创建代理。
- JDK 动态代理要求目标对象至少实现一个接口,代理对象与目标对象实现相同的接口。
- 当使用 JDK 动态代理时,Spring AOP 创建的代理对象是目标对象实现的接口的代理,而不是目标对象本身的代理。
示例:
@Component public class MyServiceImpl implements MyService { @Override public void doSomething() { System.out.println("Doing something in MyServiceImpl"); } }
如果
MyServiceImpl
实现了MyService
接口,Spring AOP 将使用 JDK 动态代理来创建MyService
接口的代理。基于类的代理(CGLIB代理):
- 如果目标对象没有实现任何接口,Spring AOP 会使用 CGLIB(Code Generation Library)来生成目标类的子类代理。
- CGLIB 代理通过继承目标类并重写目标方法来创建代理对象,因此不需要目标对象实现接口。
示例:
@Component public class MyService { public void doSomething() { System.out.println("Doing something in MyService"); } }
如果
MyService
是一个没有实现任何接口的类,Spring AOP 将使用 CGLIB 代理来创建MyService
的子类代理。
选择代理模式
- JDK 动态代理:
- 适用于目标对象实现了一个或多个接口的情况。
- 代理对象是接口的实现,而不是目标类的子类。
- CGLIB 代理:
- 适用于目标对象没有实现任何接口的情况。
- 代理对象是目标类的子类。
- CGLIB 代理性能稍逊于 JDK 动态代理,但在没有接口的类上依然表现良好。
Spring 默认情况下会尽量使用 JDK 动态代理。如果目标对象没有实现任何接口,Spring 会自动切换到使用 CGLIB 代理。你也可以通过配置明确指定使用哪种代理策略。
总结
- 代理模式 是一种设计模式,允许通过代理对象来控制对实际对象的访问,添加额外的功能。
- Spring AOP 使用代理模式来实现AOP,具体来说,使用JDK动态代理(基于接口)和CGLIB代理(基于类)来创建代理对象,以在方法调用前后执行切面逻辑。