Spring之AOP核心

AOP

AOP: 面向切面编程, AOP对OOP补充, OOP: 宏观层面的思想, 对项目的整体的架构, AOP: 站在方法层面, 不改变原来的代码基础,动态增强原来的方法

面向切面编程,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术,

OOP: 面向对象编程

 

主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。

AOP好处:

  1. 在不改变核心代码的前提, 动态的添加额外的功能

  2. 业务逻辑与非业务逻辑的解耦

  3. 程序员专心负责某一功能

  4. 业务与非业务功能灵活组装(通过配置文件组装)

AOP基于xml方式:

  1. 导入aop相关依赖:

   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context</artifactId>
       <version>${spring.version}</version>
   </dependency>
  <!--spring-aop在spring-context已经传递-->
  <!--aspectJ的依赖: 会在spring-aspects传递-->
  <!-- <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjweaver</artifactId>
              <version>1.9.7</version>
          </dependency>-->
  <!--spring整合aspectJ的依赖-->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.36</version>
  </dependency>
  1. 编写通知类, (5种增强) 一个普通类

  2. 在Spring的配置文件中配置

    • 把通知类交给spring管理

    @Component("bizLogger")
    public class BizLogger {
    • 在spring配置文件中配置aop相关配置

  
        <!--把增强类(通知类)与目标类进行织入 -->
        <aop:config>
            <!--切入点: 对那些类那些方法进行增强
              属性:
                id: 唯一标志符
                public void com.fs.aop.service.impl.UserServiceImpl.addUser(参数列表) throws Exception
                 public void com.fs.aop.service.impl.*.*(..) throws Exception
                expression:表达式 切入点表达式
                  语法: execution(修饰符? 返回值 方法名(参数) 异常?)
                  语法: ?: 0次或者1次
                  通配符:
                      *: 任意
                     ..:参数列表中使用, 任意多个任意类型的参数
            -->
              <aop:pointcut id="pointcut1" expression="execution(* com.fs.aop.service..*.*(..))"/>
              <!--织入
                 通知类方法与目标方法进行组装
                 5类通知:
                  前置通知
              -->
             <!--通知类
               ref: 通知类的bean的id
             -->
            <!--基于AspectJ的配置-->
             <aop:aspect ref="bizLogger">
                  <!--前置通知
                    method: 通知类的那个方法作为前置通知, 方法名
                     pointcut-ref: 切入点的id
                  -->
                 <!-- <aop:before method="before" pointcut-ref="pointcut1"></aop:before>-->
  
                 <!--后置通知: 目标方法正常执行之后,返回结果 的增强
                    returning: 把目标方法的返回值 赋值给afterReturning那个参数, 参数名
                 -->
                <!-- <aop:after-returning returning="result" method="afterReturning" pointcut-ref="pointcut1"></aop:after-returning>-->
  
                 <!--最终增强-->
                 <!--<aop:after method="after" pointcut-ref="pointcut1"></aop:after>-->
                 <!--异常增强
                   throwing: 把目标方法抛出异常对象赋值给增强方法那个参数接收  参数名
                 -->
                 <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut1" throwing="e"></aop:after-throwing>
                  <!--环绕增强-->
                 <aop:around method="aroundLogger" pointcut-ref="pointcut1"></aop:around>
  
             </aop:aspect>
  
        </aop:config>

基于注解的方式:

  1. 在通知类添加一个注解,表示它是通知类 @Aspect

  2. 在增强方法上添加对应的增强类型注解 @Before()

  package com.fs.aop.log;
  
  import java.sql.SQLException;
  import java.util.Arrays;
  
  import lombok.extern.slf4j.Slf4j;
  import org.apache.log4j.Logger;
  import org.aspectj.lang.JoinPoint;
  import org.aspectj.lang.ProceedingJoinPoint;
  import org.aspectj.lang.annotation.*;
  import org.springframework.stereotype.Component;
  
  /**
   * 日志增强类
   */
  @Slf4j
  @Component("bizLogger")
  @Aspect  //表示该类是一个通知类
  public class BizLogger {
    /**
     * 前置增强
     *   JoinPoint: 连接点 addUser()方法对象
     *    UserServiceImpl的addUser(User user)
     *   getTarget(): 目标方法的目标对象 UserServiceImpl对象
     *   getSignature(): 目标方法 addUser()
     *   getArgs(): 目标方法的参数的值
     * @param jp
     */
    @Before("execution(* com.fs.aop.service..*.*(..))")
    public void before(JoinPoint jp){
        log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()
                +"方法,传递的参数:"+Arrays.toString(jp.getArgs()));
    }
    
    /**
     * 后置增强
     * @param jp
     * @param result  返回值
     */
    @AfterReturning(value = "execution(* com.fs.aop.service..*.*(..))",returning = "result")
    public void afterReturning(JoinPoint jp,Object result){
        log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()
                +"方法,方法的返回值:"+result);
    }
    
    /**
     * 异常增强
     * @param jp
     * @param e 增强的异常类型
     *          SQLException: 这个异常增强只对目标方法抛出异常对象类型SQLException以及子类才执行
     */
    @AfterThrowing(value = "execution(* com.fs.aop.service..*.*(..))",throwing = "e")
    public void afterThrowing(JoinPoint jp,Exception e){
        log.error("调用"+jp.getTarget()+"的"+jp.getSignature().getName()
                +"方法发生异常"+e);
    }
    
    /**
     * 最终增强
     * @param jp
     */
    @After("execution(* com.fs.aop.service..*.*(..))")
    public void after(JoinPoint jp){
        log.info(jp.getSignature().getName()+"方法执行结束");
    }
    
    /**
     * 环绕增强
     * @param jp
     *   ProceedingJoinPoint是JoinPoint子类
     *     proceed()方法: 调用这个方法, 调用目标方法, 没有调用, 目标方法都不执行
     * @throws Throwable
     */
    @Around("execution(* com.fs.aop.service..*.*(..))")
    public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable{
        log.info(jp.getSignature().getName()+"方法开始执行");
        try {
            //执行目标方法
            Object rs = jp.proceed();
            log.info(jp.getSignature().getName()+"方法正常执行完");
            return rs;
        } catch (Exception e) {
            log.error("调用"+jp.getTarget()+"的"+jp.getSignature().getName()
                    +"方法发生异常"+e);
            throw e;
        }finally {
            log.info(jp.getSignature().getName()+"方法执行完");
        }
    }
  }

  1. 找spring配置文件,开启ApectJ的注解支持

<!--开启aspectJ注解扫描-->
    <aop:aspectj-autoproxy/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kblzxj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值