Spring知识点总结篇2 AOP
AOP篇总结
AOP 是什么?
AOP 即面向切面编程,简单地说就是将代码中重复的部分抽取出来,在需要执行的时候使用动态代理技术,在不修改[源码]()的基础上对方法进行增强。
Spring 根据类是否实现接口来判断动态代理方式,如果实现接口会使用 JDK 的动态代理,核心是 InvocationHandler 接口和 Proxy 类,如果没有实现接口会使用 CGLib 动态代理,CGLib 是在运行时动态生成某个类的子类,如果某个类被标记为 final,不能使用 CGLib 。
常用场景包括权限认证、自动缓存、错误处理、日志、调试和事务等。
如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?
AOP 的过程?
Spring AOP 由 BeanPostProcessor 后置处理器开始,这个后置处理器可以监听容器触发的 Bean 生命周期事件,向容器注册后置处理器以后,容器中管理的 Bean 就具备了接收 IoC 容器回调事件的能力。BeanPostProcessor 的调用发生在 Spring IoC 容器完成 Bean 实例对象的创建和属性的依赖注入后,为 Bean 对象添加后置处理器的入口是 initializeBean
方法。
Spring 中 JDK 动态代理通过 JdkDynamicAopProxy 调用 Proxy 的 newInstance
方法来生成代理类,JdkDynamicAopProxy 也实现了 InvocationHandler 接口,invoke
方法的具体逻辑是先获取应用到此方法上的拦截器链,如果有拦截器则创建 MethodInvocation 并调用其 proceed
方法,否则直接反射调用目标方法。因此 Spring AOP 对目标对象的增强是通过拦截器实现的。
Spring AOP有哪些通知类型,它们的执行顺序是怎样的?
在基于Spring AOP编程的过程中,基于AspectJ框架标准,spring中定义了五种类型的通知,它们分别是:
- 前置通知 (@Before) 。
- 返回通知 (@AfterReturning) 。
- 异常通知 (@AfterThrowing) 。
- 后置通知 (@After)。
- 环绕通知 (@Around) :(优先级最高)
通知执行顺序
将上面的所有通知类型写入同一个切面中,它的执行顺序为:
//增强类
//在增强类中创建方法让不同的方法代表不同的通知类型
//通过注解来创建类的对象
@Component
@Aspect//生成代理对象
public class UserProxy {
// 1 前置通知 在add()方法之前做一个before()方法 before注解表示作为前置通知 具体到哪个类那个方法作为通知(加强)
@Before(value = "execution(* com.qijie.AOP.User.add(..))")//切入点表达式
public void before(){
System.out.println("before......");
}
// 2最终通知 在方法执行之后执行 不管调用是否有一场 他最后都会输出
@After(value = "execution(* com.qijie.AOP.User.add(..))")//切入点表达式
public void after(){
System.out.println("after......");
}
// 后置通知在返回值之后执行 当有异常情况下就不会输出
@AfterReturning(value = "execution(* com.qijie.AOP.User.add(..))")//切入点表达式
public void afterreturnning(){
System.out.println("afterReturning......");
}
//异常通知 如果add()有异常才会执行
@AfterThrowing(value = "execution(* com.qijie.AOP.User.add(..))")//切入点表达式
public void afterThrowing(){
System.out.println("afterThrowing......");
}
// 环绕通知 在被增强方法前后都执行 类似jdk动态代理实现 invotionHandler接口实现
@Around(value = "execution(* com.qijie.AOP.User.add(..))")//切入点表达式
public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("Around 环绕之前......");
// 被增强的方法执行
proceedingJoinPoint.proceed();//执行被增强的方法
System.out.println("Around 环绕之后......");
}
}
AOP 的两种实现方式
AOP 采用了两种实现方式:静态织入(AspectJ 实现)和动态代理(Spring AOP实现)
AspectJ
AspectJ 是一个采用Java 实现的AOP框架,它能够对代码进行编译(一般在编译期进行),让代码具有AspectJ 的 AOP 功能,AspectJ 是目前实现 AOP 框架中最成熟,功能最丰富的语言。ApectJ 主要采用的是编译期静态织入的方式。在这个期间使用 AspectJ 的 acj 编译器(类似 javac)把 aspect 类编译成 class 字节码后,在 java 目标类编译时织入,即先编译 aspect 类再编译目标类。
Spring AOP 实现
Spring AOP 是通过动态代理技术实现的,而动态代理是基于反射设计的。Spring AOP 采用了两种混合的实现方式:JDK 动态代理和 CGLib 动态代理,分别来理解一下
- JDK动态代理:Spring AOP的首选方法。 每当目标对象实现一个接口时,就会使用JDK动态代理。目标对象必须实现接口
- CGLIB代理:如果目标对象没有实现接口,则可以使用CGLIB代理。
@AspectJ 支持
为了在Spring 配置中使用@AspectJ
,你需要启用Spring支持,以根据@AspectJ切面配置Spring AOP,并配置自动代理。自动代理意味着,Spring 会根据自动代理为 Bean 生成代理来拦截方法的调用,并确保根据需要执行拦截。
Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。
多个切面的执行顺序如何控制?
1、通常使用@Order
注解直接定义切面顺序
// 值越小优先级越高
@Order(3)
@Component
@Aspect
public class LoggingAspect implements Ordered {
2、实现Ordered
接口重写 getOrder
方法。
@Component
@Aspect
public class LoggingAspect implements Ordered {
// ....
@Override
public int getOrder() {
// 返回值越小优先级越高
return 1;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?