阅读Spring官网总结Aop用法

本文深入探讨了Spring AOP中的Advice通知类型,包括前置通知、返回后通知、异常后通知、后置通知和环绕通知,并通过实例详细解释了如何与方法参数结合使用。此外,还介绍了AOP代码解耦操作,以及如何通过切点表达式实现参数类型的查询和传递。最后,展示了三种切面覆盖方式:注解定义、方法定义和类定义。
摘要由CSDN通过智能技术生成

目录

一、Advice通知类型

1.1 前置通知

1.2 返回后通知

1.3 抛出异常后通知

1.4 后置通知

1.5 环绕通知

1.5.1 环绕通知参数JoinPoint作用

二、方法参数与advice结合

2.1 根据参数类型查询

实例

2.2 将参数传递给advice

三、Aop代码解耦操作

四、体现的三种切面覆盖方式

4.1 定义使用注解的

4.2 定义某个方法的

4.3 定义某个类的


        之前用过不少次AOP但是都没有仔细总结过,这次趁着阅读官网文档,总结一下!

一、Advice通知类型

1.1 前置通知

使用切入点表达式

    @Before("execution(* com.xyz.myapp.dao.*.*(..))")
    public void doAccessCheck() {
        // ...
    }

1.2 返回后通知

    @AfterReturning(
        pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()",
        returning="retVal")
    public void doAccessCheck(Object retVal) {
        // ...
    }

returning属性中使用的名称必须与建议方法中的参数名称相对应。当方法执行返回时,该返回值将作为相应的参数值传递到通知方法。还将匹配限制为仅返回指定类型的值的那些方法执行。

1.3 抛出异常后通知

    @AfterThrowing("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
    public void doRecoveryActions() {
        // ...
    }

希望通知仅在引发给定类型的异常时才运行,并且您通常还需要在通知正文中访问所引发的异常。您可以使用该throwing属性来限制匹配,throwing属性中使用的名称必须与建议方法中的参数名称相对应。也可限制能匹配到抛出指定类型的异常。

1.4 后置通知

    @After("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
    public void doReleaseLock() {
        // ...
    }

@AfterAspectJ中的建议被定义为“ after finally建议”,类似于try-catch语句中的finally块。它将针对从连接点(用户声明的目标方法)引发的任何结果,正常返回或异常调用。

1.5 环绕通知

    @Around("com.xyz.myapp.CommonPointcuts.businessService()")
    public Object doBasicProfiling(ProceedingJoinPoint joinPoint) throws Throwable {
        // start stopwatch
        Object retVal = joinPoint.proceed();
        // stop stopwatch
        return retVal;
    }

围绕建议在匹配方法的执行过程中“围绕”运行。它有机会在该方法运行之前和之后进行工作,并确定何时,如何以及即使该方法实际上可以运行。如果需要以线程安全的方式(例如,启动和停止计时器)在方法执行之前和之后共享状态,则通常使用环绕建议。

获取方法的第一个参数必须为类型ProceedingJoinPoint。在通知的主体,要求proceed()ProceedingJoinPoint导致运行基本方法。

proceed方法也可以传入Object[]。数组中的值在方法执行proceed时用作参数。

        Object[] args = joinPoint.getArgs();
        args[0] = "哈哈哈";
        joinPoint.proceed(args);

1.5.1 环绕通知参数JoinPoint作用

我们在使用@Around环绕通知时,方法中的参数是ProceedingJoinPoint类型的,它继承了JoinPoint接口,在此我们了解下该接口。

JoinPoint接口提供的方法:

  • getArgs():返回方法参数。

  • getThis():返回代理对象。

  • getTarget():返回目标对象。

  • getSignature():返回建议使用的方法的描述。

  • toString():打印有关所建议方法的有用描述。

二、方法参数与advice结合

2.1 根据参数类型查询

@Before("execution(* ..Sample+.sampleGenericMethod.*(..)) && args(param)")
public void beforeSampleMethod(String param) {
    // Advice implementation
}

定义sampleGenericMethod类中参数类型为String的方法才进行切面。

实例

1.切面类

@Component
@Aspect
public class GetNameAdvise {

    @Before(value = "execution(* com.example.aopdemo.demo1.controller.DemoController.alive(..))" +
            " && args(c,b)")
    public void audit(String c,Integer b) {
        System.out.println(c);
        System.out.println(b);
    }

}

2.具体方法

@RestController
public class DemoController {
    //String和Integer类型参数的方法
    @GetMapping("/aop/http/alive1")
    public String alive(String a,Integer d) {
        System.out.println("String和Integer类型参数的方法执行");
    }

    //两个String类型参数的方法
    @GetMapping("/aop/http/alive2")
    public String alive(String b,String c) {
        System.out.println("两个String类型参数的方法执行");
    }

}

3.执行结果

访问http://localhost:8080/aop/http/alive1?a=asdfaf&d=123链接时,控制台打印结果

访问http://localhost:8080/aop/http/alive2?b=asdfaf&c=ccccc链接时,控制台打印结果

由此可知,由于@Before前置增强方法两个参数是String和Integer的,所以只对参数是String和Integer的方法生效。

2.2 将参数传递给advice

@Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation() && args(account,..)")
public void validateAccount(Account account) {
    // ...
}

args(account,..)切入点表达式的一部分用于两个目的。首先,它将匹配限制为仅方法采用至少一个参数且传递给该参数的参数为的实例的方法执行Account。其次,它Account通过account 参数使实际对象可用于advice。此处跟2.1同理,不再写示例。

三、Aop代码解耦操作

当存在多个Advice通知时,面向的切点是一样的话,可以创建一个空方法,在这个方法上定义切面。后期容易修改,@Pointcut一处进行修改,它对应的的advice处处生效。

    
    //统一定义的切点
    @Pointcut("within(com.example.aopdemo.demo2.service.NeedLogService)")
    public void pointcut() {
    }

    // 定义 advise
    @Before("pointcut()")
    public void logMethodInvokeParam(JoinPoint joinPoint) {
        logger.info("---Before method {} invoke, param: {}---", joinPoint.getSignature().toShortString(), joinPoint.getArgs());
    }

    @AfterReturning(pointcut = "pointcut()", returning = "retVal")
    public void logMethodInvokeResult(JoinPoint joinPoint, Object retVal) {
        logger.info("---After method {} invoke, result: {}---", joinPoint.getSignature().toShortString(), joinPoint.getArgs());
    }

    @AfterThrowing(pointcut = "pointcut()", throwing = "exception")
    public void logMethodInvokeException(JoinPoint joinPoint, Exception exception) {
        logger.info("---method {} invoke exception: {}---", joinPoint.getSignature().toShortString(), exception.getMessage());
    }

四、体现的三种切面覆盖方式

4.1 定义使用注解的

关键字annotation

@Pointcut("@annotation(com.example.aopdemo.demo1.config.AuthChecker)")

4.2 定义某个方法的

关键字execution

  @Pointcut("execution(* com.example.aopdemo.demo1.controller.DemoController.alive())")

4.3 定义某个类的

关键字within

   @Pointcut("within(com.example.aopdemo.demo1.controller.DemoController))")

aop中Pointcut切入点指示符操作,请阅读

https://blog.csdn.net/liangjiabao5555/article/details/115362251

Spring AOP(面向切面编程)是Spring框架的一部分,它允许开发人员在应用程序中使用切面来增强对象的功能。AOP是一种编程范式,它通过将横切关注点(如日志、安全性、事务处理等)从业务逻辑中分离出来,实现了更好的模块化和复用性。 使用Spring AOP,您可以: 1. 声明切面:通过声明切面,您可以定义要拦截的方法,以及在方法执行前、执行后或执行期间要执行的代码。 2. 定义切点:切点是指在应用程序中要拦截的方法的集合。通过定义切点,您可以选择将切面应用于特定的方法或一组方法。 3. 编写通知:通知是指在应用程序中要执行的代码。通知可以在方法执行前、执行后或执行期间执行。 下面是一个简单的示例,演示如何在Spring中使用AOP: 1. 创建一个Java类,该类将充当切面。在该类中,您可以定义要拦截的方法以及通知。 ``` @Aspect public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Before method execution: " + joinPoint.getSignature().getName()); } } ``` 2. 在Spring配置文件中声明该类为切面: ``` <bean id="loggingAspect" class="com.example.aspect.LoggingAspect"/> <aop:aspectj-autoproxy/> ``` 3. 在需要拦截的方法上添加注释,以便Spring知道何时应该调用切面: ``` @Service public class UserService { @Autowired private UserDao userDao; @Transactional @Loggable public void addUser(User user) { userDao.addUser(user); } } ``` 在这个示例中,@Transactional和@Loggable是自定义注释。@Transactional注释表示该方法应该在事务中执行,@Loggable注释表示该方法应该被日志记录。 4. 运行应用程序并查看日志: ``` Before method execution: addUser ``` 在这个示例中,切面在执行UserService.addUser()方法之前拦截了该方法,并记录了一条日志消息。 这只是Spring AOP的一个简单示例,但它演示了如何使用切面来增强应用程序的功能。通过使用Spring AOP,您可以轻松地实现类似于日志记录、安全性和事务处理等横切关注点。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lllllLiangjia

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

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

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

打赏作者

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

抵扣说明:

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

余额充值