springboot项目的aop编程测试

springboot项目的aop编程测试

  1. 业务需求
    在之前的写的代码中,有部分方法写的不够完美。我的项目中的问题是,像一些操作类(新增、修改、删除)的方法没有给前端一个明显的反馈响应(比如新增成功还是失败)。所以我就想着给这些方法能不能加个注解,我们想办法监听这些方法给这些方法以切面的方式切进去一些代码。说干就干。

  2. 实现流程
    导入aop的相关jar包

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.4</version>
        </dependency>
创建一个注解类
package org.jiale.aop;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({
    
    ElementType.METHOD})
@Documented
public @interface Operation {
    
    

    /** 操作成功提示 */
    String success() default "操作成功";

    /** 操作失败提示 */
    String error() default "操作失败";
}
创建自定义监听类
package org.jiale.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 尝试自己写一个aop
 * @author ren
 * @date 2021年10月08日 14:58:56
 */
@Aspect
@Component
public class OperationListener {
    
    

    private static final Logger log = LoggerFactory.getLogger(OperationListener.class);

    //植入Advice的触发条件
    @Pointcut("@annotation(org.jiale.aop.Operation)")
    private void addTaskAction(){
    
    }

    //环绕增强
    @Around("addTaskAction()")
    public Object aroundInterviewTask(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
        log.info("拦截到了" + joinPoint.getSignature().getName() + "方法...");
        log.info("@Around : 环绕增强,未执行方法之前...");
        log.info("这里最先执行,第一步哦!!!...");
        Object proceed = joinPoint.proceed(joinPoint.getArgs());
        log.info("这里是第五步,终于回到环绕了...");
        log.info("@Around : 环绕增强结束,我浪完了...");
        return proceed;
    }

    //前置增强
    @Before("addTaskAction()")
    public void beforeInterviewTask(JoinPoint joinPoint){
    
    
        log.info("@Before : 前置增强...");
        log.info("这里是第二步,环绕执行但未执行目标方法前执行...");
    }

    //方法正常退出时执行
    @AfterReturning(returning="result",value="addTaskAction()")
    public void afterReturningInterviewTask(JoinPoint joinPoint, Object result){
    
    
        log.info("@AfterReturning : 方法正常退出时执行...");
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        Operation operation = method.getAnnotation(Operation.class);
        String success = operation.success();
        log.info("得到想要表示的操作状态为:{}",success);
        log.info("这里是第三步,目标方法执行完并未立即回到环绕方法,而是先来到这里...");
    }

    //异常抛出增强
    @AfterThrowing(throwing="ex",value="addTaskAction()")
    public void afterThrowingInterviewTask(JoinPoint joinPoint, Throwable ex){
    
    
        log.info("@AfterThrowing : 方法异常时执行...");
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        Operation operation = method.getAnnotation(Operation.class);
        String error = operation.error();
        log.info("得到想要表示的操作状态为:{}",error);
        log.info("这里是第三步,目标方法执行完并未立即回到环绕方法,而是先来到这里...");
    }

    //final增强,不管是抛出异常或者正常退出都会执行
    @After("addTaskAction()")
    public void afterInterviewTask(JoinPoint joinPoint){
    
    
        log.info("@After : 方法执行完必执行...");
        log.info("这里是第四步,从第三步出来继而来到这里...");
    }
}
给要监听的方法加上自定义注解
 /**
     * 修改合同关键字匹配库
     * @param library
     * @return
     */
    @PostMapping("/edit")
    @ResponseBody
    @Operation
    public Result editSave(CostKeywordMatchLibrary library){
    
    
        return toAjax(costKeywordMatchLibraryService.update(library));
    }
测试结果

在这里插入图片描述
注意:这里是springboot项目,记得要把加@Aspect的监听类交给框架管 理,否则项目不报错也切不进去。如果项目是springMVC + spring的话,要加入配置:

<!--开启AOP的注解支持-->
	<aop:aspectj-autoproxy proxy-target-class="true"/>

最好加到springmvc.xml文件中去,不要加到springApplication.xml文件中。理论上如果切的是service层的话是可以加到springApplication.xml文件的,但好多人都切不到,我也没测。但加到springmvc.xml文件中是肯定没问题的。

猜你喜欢

转载自blog.csdn.net/weixin_53514362/article/details/120673019