SpringBoot 的面向切面编程(AOP)

1、确定连接点

 
连接点:对应的是具体被拦截的对象。在什么地方使用AOP,也就是项目需要使用AOP的是哪个类的哪个方法。Spring               AOP只能对方法进行拦截,所以我们采用@AspectJ注解实现AOP时,首先要确定需要拦截的方法,让它能织入
              到约定的流程中。

 

2、定义切点

 
代码中,我们使用注解@Pointcut来定义切点(具体看示例代码)。
 

以一个表达式来举例说明:executiong(* com.springboot.pro.service.impl.UserServiceImpl.printUser(…))

  • execution 表示在执行的时候,拦截里面的正则匹配的方法;
  • * 表示任意返回类型的方法;
  • com.springboot.pro.service.impl.UserServiceImpl 表示指定目标对象的全限定名称;
  • printUser 表示指定目标对象的方法;
  • (…) 表示任意参数进行匹配。
     
     

                                                                         AspectJ的指示器

项目类型描述
arg()限定连接点方法参数
executing()用于匹配值连接点的执行方法
@args()通过连接点方法参数上的注解进行限定
this限制连接点匹配AOP代理Bean引用为指定的类型
target目标对象(即被代理对象)
@target()限制目标对象的配置了指定的注解
within限制连接点匹配指定的类型
@within限定连接点带有匹配注解类型
@annotation()限定带有指定注解的连接点

 

3、开发切面

 
通过切面可以描述AOP其他的信息,用于描述流程的织入。通俗点讲,切面就是AOP在连接点方法上的一些扩展。
开发切面时,有5种通知。
 

3.1 AspectJ 支持 5 种类型的通知注解

 

3.1.1 前置通知 @Before

@Before: 前置通知, 在方法执行之前执行。需要注意的是,前置通知无法返回响应。

 

3.1.2 后置通知 @After

        @After: 后置通知, 在方法执行之后执行。无论是否发生异常,都进行执行的通知。需要注意的是,在后置通知中,不能访问目标方法的执行结果。原因可能在执行过程中发生异常而无法得到结果。

 

3.1.3 返回通知 @AfterRunning

        @AfterRunning: 返回通知, 在方法返回结果之后执行。在目标方法正常结束时,才执行的通知。返回通知可以访问到方法的返回值。

 

3.1.4 异常通知 @AfterThrowing

@AfterThrowing: 异常通知, 在方法抛出异常之后。

 

3.1.5 环绕通知 @Around

        @Around: 环绕通知, 围绕着方法执行。环绕通知类似于动态代理。在使用环绕通知时,需要明确调用 ProceedingJoinPoint的proceed()方法来执行被代理的方法。否则会导致通知被执行了,但是目标方法没有被执行。同时需要注意的是,环绕通知的方法需要有返回值(该返回值就是返回目标方法执行之后的结果,即调用ProceedingJoinPoint.proceed()的返回值),否则会出现空指针异常。

 

4、示例代码

 



import com.alibaba.fastjson.JSON;
import com.github.pagehelper.util.StringUtil;
import com.huajie.servera.common.CommonResult;
import com.huajie.servera.enu.ResultEnum;
import com.huajie.servera.util.CookieUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;

/**
 * @title: ControllerAop
 * @description: TODO
 * @date 2019/5/29 17:17
 */
@Configuration
@Order(1)//设置切面的优先级,数字越小优先级越高
@Aspect
public class ControllerAop {

   private final static Logger logger = LoggerFactory.getLogger(ControllerAop.class);


    public ControllerAop(){
        logger.info("=============初始化ControllerAop===============");
    }

   @Pointcut("execution(* com.pro.servera.controller.*.*(..))")
   public void pointCut() {

   }

    /**
     * 环绕通知
     */ 
    @Around("pointCut()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) {
        Object result = null;
        // 获取将要执行的方法名称
        String methodName = pjp.getSignature().getName();
        // 获取执行方法的参数
        Object[] argst = pjp.getArgs();
        if (argst.length > 0) {
          // 获取第一个参数的类型
          String firstType = argst[0].getClass().getName();
        }
        try {
            // 执行原方法
            result = pjp.proceed();
        } catch (Throwable t) {
            logger.info("=========环绕通知异常=============");
            t.printStackTrace();
        }
        return result;

    }


    /**
     * 声明该方法是一个前置通知,
     * 方法执行之前执行
     */
    @Before("pointCut()")
    public void before(ProceedingJoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
    }

    /**
     * 声明该方法是一个后置通知,目标方法执行后执行,
     * 就算目标方法抛出异常也会执行
     * 但是后置通知不能访问目标方法返回的结果
     */
    @After("pointCut()")
    public void after(ProceedingJoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
    }

    /**
     * 在目标方法正常执行完了之后执行,
     * 可以访问到方法的返回值:result
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void afterReturning(ProceedingJoinPoint joinPoint, Object result) {
    }

    /**
     * 在目标方法抛出异常执行,也可以指定出现制定异常时执行,
     * Exception改为需要指定的一场类型
     */
    @AfterThrowing(value = "pointCut()",throwing = "e")
    public void afterThorwing(ProceedingJoinPoint joinPoint, Exception e) {
    }



}

 
不要忘记SpringBoot启动类添加注解@EnableAspectJAutoProxy(proxyTargetClass=true)
  
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot实现AOP面向切面编程的具体方法如下: 1. 首先,你需要在项目的pom.xml文件中添加spring-boot-starter-aop依赖。可以参考以下代码: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 2. 然后,你需要编写一个用于拦截的bean。这个bean将包含你想要在目标方法执行前后执行的逻辑。你可以使用注解或者编程方式来定义切面。例如,你可以使用@Aspect注解来定义一个切面,然后在切面的方法上使用@Before、@After等注解来定义具体的拦截行为。 3. 接下来,你需要将切面应用到目标对象上,创建代理对象。这个过程称为织入(Weaving)。在Spring Boot中,你可以使用@EnableAspectJAutoProxy注解来启用自动代理,它会根据切面定义自动创建代理对象。 总而言之,Spring Boot实现AOP面向切面编程的具体方法包括:添加依赖、编写用于拦截的bean,以及启用自动代理。这样就能实现在目标方法执行前后执行特定逻辑的效果了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot整合aop面向切面编程过程解析](https://download.csdn.net/download/weixin_38689551/12743012)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SpringBoot实现AOP面向切面编程](https://blog.csdn.net/weixin_52536274/article/details/130375560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值