@AspectJ中的几种通知方式详解

本文来详细说下@AspectJ中的几种通知方式


概述

当Spring 2.0发布以后,Spring AOP增加了新的使用方式,Spring AOP集成了AspectJ。我们最常用的就是这个版本的Spring AOP。

主要有如下变化

  • 可以用POJO来定义Aspect和Adivce,并提供了一系列相应的注解,如@Aspect和@Around等。而不用像1.x版本中实现相应的接口
  • 支持aspectj中的pointcut的表达方式,我们都深有体会哈

在这里插入图片描述


通知方式说明

下面这个是官网对@AspectJ中的几种通知方式的说明

在这里插入图片描述


一个例子

导入@AspectJ注解的maven

<!-- @Aspect-->
 <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
 </dependency>

选择连接点,就是业务方法,可以看作动态代理中的目标对象

Spring 是方法级别的 AOP 框架,我们主要也是以某个类额某个方法作为连接点,另一种说法就是:选择哪一个类的哪一方法用以增强功能

package cn.wideth.buz.test;

public class Landlord {

    public void service() {

        // 仅仅只是实现了核心的业务功能
        System.out.println("业务方法 => service()");
//        throw new RuntimeException();

    }
}

我们在这里就选择上述 Landlord 类中的 service() 方法作为连接点

创建切面

选择好了连接点就可以创建切面了,我们可以把切面理解为一个拦截器,当程序运行到连接点的时候,被拦截下来,在开头加入了初始化的方法,在结尾也加入了销毁的方法而已,在 Spring 中只要使用 @Aspect 注解一个类,那么 Spring IoC 容器就会认为这是一个切面了。

package cn.wideth.buz.test;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

/***
 * 切面(aspect)。类是对物体特征的抽象,
 * 切面就是对横切关注点的抽象
 */
@Aspect
public class Broker {

    /***
     * 连接点(joinpoint)。被拦截到的点,因为Spring只
     * 支持方法类型的连接点,所以在Spring中连接点指的就
     * 是被拦截到的方法,实际上连接点还可以是字段或者构造器
     */
    @Pointcut("execution(* cn.wideth.buz.test.Landlord.service(..))")
    public void lService() {
    }

    /***
     * @Before在方法执行之前执行
     */
    @Before("lService()")
    public void before(){
        System.out.println("before()");
    }

    /***
     * @After在方法执行之后执行
     */
    @After("lService()")
    public void after(){
        System.out.println("after()");
    }

    /***
     * @Around围绕着方法执行
     */
    @Around("lService()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        System.out.println("<== around");
        Object result = joinPoint.proceed();
        System.out.println("around ==>");
        return result;
    }

    /***
     * @AfterReturning在方法返回结果之后执行
     */
    @AfterReturning("lService()")
    public void afterReturning(){
        System.out.println("AfterReturning()");
    }

    /***
     * @AfterThrowing在方法抛出异常之后执行
     */
    @AfterThrowing("lService()")
    public void afterThrowing(){
        System.out.println("afterThrowing()");
    }

}

启用AOP

因为使用注解的方式来操作AOP,所以编写一个配置类来开启AOP

package cn.wideth.buz.test;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

// 启用AOP
@EnableAspectJAutoProxy
public class AspectJConfig {

    @Bean
    public Landlord getLandlord() {
        return new Landlord();
    }
}

测试 AOP

package cn.wideth.buz.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AspectJConfig.class, Broker.class);

        Landlord landlord = context.getBean(Landlord.class);
        landlord.service();
        context.close();

    }
}

测试结果

在这里插入图片描述

Adivce之间的顺序关系

正确的情况下

@Around->@Before->方法执行->@AfterReturning ->@After-> @Around


本文小结

本文介绍了@AspectJ中的几种通知方式,以及5种通知的先后顺序。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值