Spring AOP切面编程实现原理

1.概述

Spring AOP是Spring框架中极为重要的核心功能,和Spring IOC并称为Spring的两大核心模块。顾名思义,AOP 即 Aspect Oriented Programming,翻译为面向切面编程。OOP面向对象编程是纵向地对一个事物的抽象,一个对象包括静态的属性信息、动态的方法信息等。而AOP是横向地对不同事物的抽象,属性与属性、方法与方法、对象与对象都可以组成一个切面,而用这种思维去设计编程的方式叫做面向切面编程。

Spring AOP 是利用 CGLIB 和 JDK 动态代理等方式来实现运行期动态方法增强,其目的是将与业务无关的代码单独抽离出来,使其逻辑不再与业务代码耦合,从而降低系统的耦合性,提高程序的可重用性和开发效率。因而 AOP 便成为了日志记录、监控管理、性能统计、异常处理、权限管理、统一认证等各个方面被广泛使用的技术。我们之所以能无感知地在Spring容器bean对象方法前后随意添加代码片段进行逻辑增强,是由于Spring 在运行期帮我们把切面中的代码逻辑动态“织入”到了bean对象方法内,所以说AOP本质上就是一个代理模式

对于代理模式和动态代理技术相关知识点不熟悉的,请先看看之前我总结的:浅析动态代理实现与原理,学习一下动态代理知识点,了解CGlib 和 JDK 两种不同动态代理实现方式原理与区别,并且上面说了Spring AOP就是动态代理技术实现的,只有了解动态代理技术,才能快速掌握今天主题AOP。

2.AOP切面编程示例

既然AOP切面编程的特点就是可以做到对某一个功能进行统一切面处理,对业务代码无侵入,降低耦合度。那么下面我们就根据日志记录这一功能进行实例讲解,对于AOP的编程实现可以基于XML配置,也可以基于注解开发,当下注解开发是主流,所以下面我们基于注解进行示例展示。

切面类

定义一个切面类,来进行日志记录的统一打印。

csharp复制代码@Component  // bean组件
@Aspect // 切面类
public class LogAspect {

  // 切入点
  @Pointcut("execution(* com.shepherd.aop.service.*.*(..))")
  private void pt(){}

  /**
   * 前置通知
   */
    @Before("pt()")
  public  void beforePrintLog(){
    System.out.println("前置通知beforePrintLog方法开始记录日志了。。。");
  }

  /**
   * 后置通知
   */
  @AfterReturning("pt()")
  public  void afterReturningPrintLog(){
    System.out.println("后置通知afterReturningPrintLog方法开始记录日志了。。。");
  }
  /**
   * 异常通知
   */
    @AfterThrowing("pt()")
  public  void afterThrowingPrintLog(){
    System.out.println("异常通知afterThrowingPrintLog方法开始记录日志了。。。");
  }

  /**
   * 最终通知
   */
  @After("pt()")
  public  void afterPrintLog(){
    System.out.println("最终通知afterPrintLog方法开始记录日志了。。。");
  }

  /**
   * 环绕通知
   */
  @Around("pt()")
  public Object aroundPrintLog(ProceedingJoinPoint pjp){
    Object rtValue = null;
    try{
      Object[] args = pjp.getArgs();//得到方法执行所需的参数

      System.out.println("环绕通知aroundPrintLog方法开始记录日志了。。。前置");

      rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
      System.out.println(rtValue);

      System.out.println("环绕通知aroundPrintLog方法开始记录日志了。。。后置");
      return rtValue;
    }catch (Throwable t){
      System.out.println("环绕通知aroundPrintLog方法开始记录日志了。。。异常");
      throw new RuntimeException(t);
    }finally {
      System.out.println("环绕通知aroundPrintLog方法开始记录日志了。。。最终");
    }
  }
}

首先@Aspect表示该类是一个切面类,只要满足@Pointcut标注的切点表达式,就可以执行相应通知方法增强逻辑打印日志。同时我这里写了aop的所有通知:前置、后置、异常、最终、环绕,其实环绕通知就能实现其他四种通知效果了,但是我为了演示所有通知方式和通知方法执行顺序,就全写了,你可以观察一下执行结果。

业务方法

随便写一个业务方法:

csharp复制代码public interface MyService {
  String doSomething();
}
typescript复制代码@Service
public class MyServiceImpl implements MyService{

  @Override
  public String doSomething() {
    return "========>>> 业务方法执行成功啦!!! ========>>> ";
  }
}

配置类

声明一个配置类开启aop代理功能和bean组件扫描

less复制代码@Configuration //配置类
@ComponentScan(basePackages = {"com.shepherd.aop"})   //扫描bean组件
@EnableAspectJAutoP
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值