spring学习(5)

举报
幼儿园老大* 发表于 2024/09/27 21:31:24 2024/09/27
【摘要】 切面对组件类(@component) 添加 @Aspect 注解,表示该类为切面类。增强类型前置通知切面方法注解 @Before 表示目标方法调用前,执行该切面方法。@Before("execution(* com.company.project.service.Meal.eat(..))")public void cook() { System.out.println("cook")...

切面

对组件类(@component) 添加 @Aspect 注解,表示该类为切面类。

增强类型

前置通知

切面方法注解 @Before 表示目标方法调用前,执行该切面方法。



@Before("execution(* com.company.project.service.Meal.eat(..))")
public void cook() {
    System.out.println("cook");
}Copy to clipboardErrorCopied

后置通知

  • 切面方法注解 @After 表示目标方法返回或抛出异常后,执行该切面方法。
  • 切面方法注解 @AfterReturning 只在目标方法返回后,执行该切面方法。
  • 切面方法注解 @AfterThrowing 只在目标方法抛出异常后,执行该切面方法。


@AfterReturning("execution(* com.company.project.service.Meal.eat(..))")
public void clean() {
    System.out.println("clean");
}Copy to clipboardErrorCopied

环绕通知

切面方法注解 @Around 表示切面方法执行过程中,执行目标方法。

传入参数为 ProceedingJoinPoint 类对象,表示目标方法。在切面方法中调用其 proceed 方法来执行。



@Around("execution(* com.company.project.service.Meal.eat(..))")
public void party(ProceedingJoinPoint pj) {
    try {
        System.out.println("cook");
        pj.proceed();
        System.out.println("clean");
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
}Copy to clipboardErrorCopied

切点声明

在切面方法中需要声明切面方法要切入的目标方法,execution 指示器是我们定义切点时最主要使用的指示器。

格式为: execution(返回数据类型 路径.类.方法(传入参数类型))

参数 功能
execution(* com.company.project.service.Meal.eat(..)) 执行 Meal 类的 eat 方法时切入
execution(* com.company.project.service.Meal.eat(int,String)) 执行 Meal 类的 eat(int,String) 方法时切入
execution(* com.company.project.service.Meal.*(..)) 执行 Meal 类的所有方法时切入
execution(* com.company.project.service.*.*(..)) 执行 service 包内的任意方法时切入(不包含子包)
execution(* com.company.project.service..*.*(..)) 执行 service 包内的任意方法时切入(包含子包)
execution(public * *(..)) 执行所有目标类的所有 public 方法时切入
execution(* pre*(...)) 执行所有目标类所有以 pre 为前缀的方法时切入

还有一些其他指示器:

参数 功能
within(com.company.project.service.*) 执行 service 包内的任意方法时切入
this(com.company.project.service.AccountService) 执行实现 AccountService 接口的代理对象的任意方法时切入
target(com.company.project.service.AccountService) 执行实现 AccountService 接口的目标对象的任意方法时切入
args(java.io.Serializable) 任何一个只接受一个参数,并且运行时所传入的参数是 Serializable 接口的方法
  • 多个匹配条件之间使用链接符连接: &&||! 
  • within 指示器表示可以选择的包,bean 指示器可以在切点中选择 bean 。

如参数 execution(String com.company.project.service.test1.IBuy.buy(double)) && args(price) && bean(girl)

要求返回类型为 String ;参数类型为 double ;参数名为 price ;调用目标方法的 bean 名称为 girl 。

简化代码

对于类中要频繁要切入的目标方法,我们可以使用 @Pointcut 注解声明切点表达式,简化代码。



@Aspect
@Component
public class EatPlus {

    @Pointcut("execution(* com.company.project.service.Meal.eat(..))")
    public void point(){}

    @Before("point()")
    public void cook() {
        System.out.println("cook");
    }

    @Around("point()")
    public void party(ProceedingJoinPoint pj) {
        try {
            System.out.println("cook");
            pj.proceed();
            System.out.println("clean");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    @Pointcut("execution(String com.company.project.service.Meal.eat(double)) && args(price) && bean(people)")
    public void point2(double price) {
    }

    @Around("point2(price)")
    public String pay(ProceedingJoinPoint pj, double price){
        try {
            pj.proceed();
            if (price > 100) {
                System.out.println("can not afford");
                return "没有购买";
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return "购买";
    }
}Copy to clipboardErrorCopied
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。