首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
AOP引入:OOP存在哪些局限性?
AOP常见使用场景
AOP概念:Aspect、Join Point和Advice等术语应该如何理解?
Java AOP设计模式:代理、判断和拦截器模式
Java AOP代理模式(Proxy):Java静态代理和动态代理的区别是什么?
Java AOP判断模式(Predicate):如何筛选Join Point?
Java AOP拦截器模式(Interceptor):拦截执行分别代表什么?
Spring AOP 功能概述:核心特性、编程模型和使用限制
Spring AOP编程模型:注解驱动、XML配置驱动和底层API
Spring AOP设计目标:Spring AOP与 AOP框架之间的关系是竞争还是互补?
Spring AOP Advice类型:Spring AOP丰富了哪些AOP Advice呢?
Spring AOP代理实现:为什么Spring Framework选择三种不同AOP实现?
JDK动态代理:为什么Proxy.newProxyInstance会生成新的字节码?
CGLIB动态代理:为什么Java动态代理无法满足AOP的需要?
AspectJ代理代理:为什么Spring推荐AspectJ注解?
AspectJ基础:Aspect、Join Points、Pointcuts和Advice语法和特性
AspectJ注解驱动:注解能完全替代AspectJ语言吗?
Spring核心基础:《小马哥讲Spring核心编程思想》还记得多少?
@AspectJ注解驱动
编程方式创建 @AspectJ代理
XML配置驱动 - 创建AOP代理
标准代理工厂API - ProxyFactory
@AspectJ Pointcut指令与表达式:为什么Spring只能有限支持?
XML配置Pointcut
API实现Pointcut
@AspectJ拦截动作:@Around与@Pointcut有区别吗?
XML配置Around Advice
API实现Around Advice
@AspectJ前置动作:@Before与@Around谁优先级执行?
XML配置Before Advice
API实现Before Advice
@AspectJ后置动作 - 三种After Advice之间的关系?
XML配置三种After Advice
API实现三种After Advice
自动动态代理
替换TargetSource
Spring AOP API整体设计
接入点接口 - Joinpoint
Joinpoint条件接口 - Pointcut
Pointcut操作 - ComposablePointcut
Pointcut便利实现
Pointcut AspectJ实现 - AspectJExpressionPointcut
Joinpoint执行动作接口 - Advice
Joinpoint Before Advice标准实现
Joinpoint Before Advice AspectJ实现
Joinpoint After Advice标准实现
Joinpoint After Advice AspectJ实现
Advice容器接口 - Advisor
Pointcut与Advice连接器 - PointcutAdvisor
Introduction与Advice连接器 - IntroductionAdvisor
Advisor的Interceptor适配器 - AdvisorAdapter
AdvisorAdapter实现
AOP代理接口 - AopProxy
AopProxy工厂接口与实现
JDK AopProxy实现 - JdkDynamicAopProxy
当前位置:
首页>>
技术小册>>
Spring AOP 编程思想(上)
小册名称:Spring AOP 编程思想(上)
### Java AOP代理模式(Proxy):Java静态代理和动态代理的区别是什么? 在深入探讨Spring AOP(面向切面编程)之前,理解Java中的代理模式,特别是静态代理与动态代理的区别,是至关重要的基础。代理模式是一种常用的设计模式,它允许我们为其他对象提供一种代理以控制对这个对象的访问。在Java中,代理模式主要有两种实现方式:静态代理和动态代理。这两种方式在实现细节、灵活性以及应用场景上存在显著差异。 #### 一、静态代理 ##### 1. 定义与特点 静态代理是指代理类在程序编译时就已经确定,它通常是由程序员手动编写的。静态代理类会实现与目标对象相同的接口,并在其内部封装目标对象,通过调用目标对象的方法来实现对目标对象的增强或控制。 **特点**: - **编译时确定**:代理类的.java文件在编译时就已存在,代理关系在编译时就已确定。 - **手动编写**:需要程序员根据目标接口手动编写代理类代码。 - **接口约束**:目标类和代理类都需实现相同的接口。 - **灵活性低**:当接口增加方法时,所有实现了该接口的类(包括代理类)都需要实现新方法,增加了维护成本。 ##### 2. 实现示例 假设有一个`Subject`接口和两个实现类`RealSubject`(真实对象)与`StaticProxy`(静态代理类)。 ```java // Subject 接口 interface Subject { void request(); } // RealSubject 真实对象 class RealSubject implements Subject { @Override public void request() { System.out.println("Executing real request."); } } // StaticProxy 静态代理类 class StaticProxy implements Subject { private Subject realSubject; public StaticProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void request() { preRequest(); realSubject.request(); // 调用真实对象的方法 postRequest(); } private void preRequest() { System.out.println("Before real request."); } private void postRequest() { System.out.println("After real request."); } } // 使用示例 public class StaticProxyDemo { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject proxy = new StaticProxy(realSubject); proxy.request(); // 调用代理类的方法 } } ``` #### 二、动态代理 ##### 1. 定义与特点 动态代理是指代理类在程序运行时动态生成,而不是在编译时确定。Java动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。动态代理类能够代理任何实现了特定接口的类,这使得它非常灵活且易于扩展。 **特点**: - **运行时生成**:代理类的.class文件在运行时由JVM动态生成,代理关系在运行时确定。 - **自动编写**:不需要程序员手动编写代理类代码,降低了开发成本。 - **接口约束**:目标对象必须实现至少一个接口,因为动态代理是基于接口的。 - **高度灵活**:可以在不修改目标对象代码的情况下,增加新的功能或修改现有功能。 ##### 2. 实现示例 假设我们还是使用上面的`Subject`接口和`RealSubject`类,现在使用动态代理来实现代理功能。 ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // InvocationHandler 实现 class DynamicProxyHandler implements InvocationHandler { private Object target; public DynamicProxyHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { preRequest(); Object result = method.invoke(target, args); // 调用目标对象的方法 postRequest(); return result; } private void preRequest() { System.out.println("Before method execution."); } private void postRequest() { System.out.println("After method execution."); } // 创建代理对象的方法 @SuppressWarnings("unchecked") public static <T> T newProxyInstance(Class<T> interfaceClass, Object target) { return (T) Proxy.newProxyInstance( interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new DynamicProxyHandler(target) ); } } // 使用示例 public class DynamicProxyDemo { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject proxy = DynamicProxyHandler.newProxyInstance(Subject.class, realSubject); proxy.request(); // 调用代理类的方法 } } ``` #### 三、静态代理与动态代理的区别 1. **编译与运行时**: - 静态代理是在编译时就确定了代理关系,代理类的.java文件是手动编写的。 - 动态代理则是在运行时动态生成代理类的.class文件,代理关系在运行时确定。 2. **灵活性**: - 静态代理由于需要手动编写代理类,当接口增加方法时,所有代理类都需要修改,灵活性较低。 - 动态代理则无需手动编写代理类,当接口增加方法时,无需修改代理代码,灵活性高。 3. **性能**: - 静态代理因为是编译时确定的,所以在性能上通常比动态代理稍好(尽管这种差异在大多数情况下可以忽略不计)。 - 动态代理因为涉及到反射调用,所以在性能上可能会稍逊一筹,但换来的是更高的灵活性和更少的代码量。 4. **使用场景**: - 静态代理适用于代理类较少,且接口变化不大的情况。 - 动态代理则适用于代理类较多,或接口经常变化的情况,以及需要动态控制代理逻辑的场景。 5. **实现复杂度**: - 静态代理实现简单,但维护成本较高。 - 动态代理实现相对复杂(主要是理解反射机制),但维护成本较低。 #### 结论 静态代理和动态代理各有优缺点,选择哪种方式取决于具体的应用场景和需求。在Spring AOP的上下文中,动态代理因其高度的灵活性和易用性而被广泛使用,特别是在需要实现横切关注点(如事务管理、日志记录等)时,动态代理提供了一种非常有效的解决方案。通过理解静态代理和动态代理的区别,我们可以更好地利用Java的代理机制,为应用程序的设计和实现带来更多的灵活性和可维护性。
上一篇:
Java AOP设计模式:代理、判断和拦截器模式
下一篇:
Java AOP判断模式(Predicate):如何筛选Join Point?
该分类下的相关小册推荐:
Java面试指南
Mybatis合辑4-Mybatis缓存机制
Java并发编程实战
SpringBoot合辑-初级篇
经典设计模式Java版
Java语言基础13-类的加载和反射
Mybatis合辑2-Mybatis映射文件
手把手带你学习SpringBoot-零基础到实战
Java语言基础15-单元测试和日志技术
Java并发编程
Spring AOP 编程思想(下)
JAVA 函数式编程入门与实践