Spring中的AOP(四)——基于Annotation的配置方式(二)

Easter79
• 阅读 622

使用After增强处理

    Spring还提供了一个After增强处理,它与AfterReturning有点类似,但也有区别:

  • AfterReturning增强处理只有在目标方法正确完成后才会被织入

  • After增强处理不管目标方法如何结束(正确还是异常),它都会被织入

    正是因为这个特点,因此After增强处理必须准备处理正常返回和异常返回两种情况,这种增强处理通常用于释放资源。使用@After注解标注一个方法,即可将该方法转换为After增强处理。使用@After注解是需要指定一个value属性,用于指定该增强处理的切入点,既可以是一个已有的切入点,也可以直接定义切入点表达式。

    在com.abc.advice包下面增加AfterAdviceTest,这个类定义了一个After增强处理:

@Aspect
public class AfterAdviceTest {
    @After(value="execution(* com.abc.servie.impl.*.afterAdvice*(..))")
    public void releaseResource() {
        System.out.println("模拟释放数据库连接");
    }
}

     并在AdviceManager类中增加以下内容:

//将被AfterAdvice的releaseResource方法匹配
public void afterAdvice() {
    System.out.println("方法: afterAdvice");
}

    上面定义了一个After增强处理,不管切入点的目标方法如何结束,该增强处理都会被织入。下面是测试结果:

Spring中的AOP(四)——基于Annotation的配置方式(二)

使用Around增强处理

    @Around注解用于标注Around增强处理,它近似等于Before增强处理和AfterReturning增强处理的总和,Around增强处理既可以在执行目标方法前织入增强动作,也可以在目标方法之后织入增强动作。

    与@Before和@AfterReturning不同的是,@Around甚至可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标方法的执行。@Around可以修改目标方法的参数值,也可以修改目标方法的返回值。

    @Around的功能虽然强大,但通常需要在线程安全的环境下使用,因此,如果使用普通的@Before和@AfterReturning就能解决的问题,就没有必要使用@Around了。如果需要目标方法执行之前和执行之后共享某种数据状态,则应该考虑使用@Around;尤其是需要使用增强处理阻止目标方法的执行,或者需要改变目标方法的参数和执行后的返回值时,就只能使用@Around了。

    可以想象,使用@Around时,也需要指定一个value属性,这个属性依然是用于指定切入点。另外,当定义一个Around增强处理时,该方法的第一个形参必须是ProceedingJoinPoint类型(就是说至少包含一个形参),在增强处理方法体内,调用ProceedingJoinPoint的proceed()方法才会执行目标方法——这就是Around增强处理可以完全控制目标方法的执行时机、如何执行的关键,如果增强处理的方法体内没有调用这个proceed()方法,则目标方法不会执行。

    调用proceed()方法时,还可以传入一个Object[]对象,该数组中的值将被传入目标方法作为执行方法的实参。因此我们可以通过这个参数,修改方法的参数值。

在com.abc.advice包下面增加AroundAdviceTest,这个类定义了一个Around增强处理:

package com.abc.advice;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AroundAdviceTest {
    @Around(value="execution(* com.abc.service.*.around*(..))")
    public Object process(ProceedingJoinPoint point) throws Throwable {
        System.out.println("模拟执行目标方法前的增强处理:事务开始...");
        //修改目标方法的参数
        String[] params = new String[]{"param1"};
        //执行目标方法,并保存目标方法执行后的返回值
        Object returnValue = point.proceed(params);
        System.out.println("模拟执行目标方法后的增强处理:事务结束...");
        //返回修改后的返回值
        return "方法实际返回值:" + returnValue + ",这是返回值的后缀";
    }
}

上面定义了一个AroundAdviceTest切面,该切面包含了一个Around增强处理:process()方法,该方法中第一行代码用于模拟调用目标方法之前的处理,第二行修改了目标方法的第一个参数,接下来调用目标方法,后面模拟调用目标方法之后的处理和对返回值的修改。正如前面说的,通过这个process方法,我们可以增加类似于@Before和@AfterReturning的增强处理,可以决定什么时候执行目标方法,可以修改目标方法的参数值,还可以修改目标方法的返回值,真是想做什么就做什么啊!

在AdviceManager类中增加以下内容:

//将被AroundAdvice的process方法匹配
public String aroundAdvice(String param1) {
    System.out.println("方法: aroundAdvice");
    return param1;
}

    在com.abc.main.AOPTest中加入方法的调用,触发切点:

String result = manager.aroundAdvice("param1");
System.out.println("返回值:" + result);

    执行测试类,结果如下:

    Spring中的AOP(四)——基于Annotation的配置方式(二)

    需要注意的是,当调用ProceedingJoinPoint的proceed()方法时,传入的Object[]参数值将作为目标方法的参数,如果这个数组长度与目标方法的参数个数不等,或者数组元素的类型和目标方法的参数类型不匹配,程序就会出现异常。

    《Spring中的AOP系列三、四、五》的代码在这里:点击下载,欢迎留言提意见。

    【未完,待续】

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
Spring的AOP的注解的通知类型,切入点的注解
Spring的注解的AOP的通知类型@Before:前置通知@AfterReturning:后置通知@Around:环绕通知@AfterThrowing:异常抛出通知@After:最终通知@Pointcut:切入点的注解1/
Easter79 Easter79
3年前
Spring中的AOP(三)——基于Annotation的配置方式(一)
    AspectJ允许使用注解用于定义切面、切入点和增强处理,而Spring框架则可以识别并根据这些注解来生成AOP代理。Spring只是使用了和AspectJ5一样的注解,但并没有使用AspectJ的编译器或者织入器,底层依然使用SpringAOP来实现,依然是在运行时动态生成AOP代理,因此不需要增加额外的编译,也不需要AspectJ的织入器支持。
Easter79 Easter79
3年前
Spring中的AOP(七)——基于XML配置文件方式的AOP
  除了前面介绍的基于JDK1.5的注解方式来定义切面,切入点和增强处理外,SpringAOP也允许直接使用XML配置文件来管理它们。在JDK1.5之前,只能使用配置文件的方式来管理,在Spring2.X后提供了一个新的aop命名空间来定义切面、切入点和增强处理。相比之下,使用XML配置文件方式有如下优点:如果没有使用JDK1.5以上
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
AOP的基本术语
通知、增强(Advice)通知就是你想要的功能,在特定的连接点,AOP框架执行的动作。Spring切面可以应用5种类型的通知:前置通知(Before):在目标方法被调用之前调用通知功能;后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;返回通知(Afterreturni
Easter79 Easter79
3年前
Spring中的AOP(五)——在Advice方法中获取目标方法的参数
获取目标方法的信息    访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点。JoinPoint里包含了如下几个常用的方法:Object\\getArgs:返回目标方法的参数Signature
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k