基于AspectJ实现AOP操作

简介: 基于AspectJ实现AOP操作

前言:AspectJ 不是 Spring框架的组成部分,是独立的AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用进行 AOP 操作

一.AOP相关术语

比如某个类中有如下4个方法:

Class A{
    
    add();
    delete();
    update();
    select();
}

1.连接点(JoinPoint)

类A中的4个方法都可能被增强,这4个方法成为连接点

2.切入点(PointCut)

如果我实际只增强 add()和update()方法,则add()和update()称为切入点;
即实际被真正增强方法

3.通知、增强(Advice)

比如我增强add()方法,在add()方法执行之前加上判断代码,这个判断代码就称为通知;
即实际增强的逻辑部分称为通知或增强

通知的五种类型:

前置通知 :在执行add()方法之前有一些逻辑部分后置通知(返回通知):在执行add()方法之后有一些逻辑部分环绕通知:在执行add()方法之前和之后都有一些逻辑部分异常通知:当执行add()方法出现异常时会执行的逻辑部分最终通知:与try-catch-finally中的finally类似,最终一定会执行的逻辑部分

4.切面(Aspect)

切面是一个动作,把我们的通知应用到切入点的过程叫做切面。
比如把判断代码加到add()方法之前的这个过程称为切面。

二.切入点表达式

切入点表达式的作用是知道对哪个类里面的哪个方法进行增强。

1.切入点表达式的格式

execution([权限修饰符][返回值类型][类全路径][方法名称]([参数列表])[异常])
其中返回值类型、方法名称和参数列表是必填的。

2.切入点表达式通配符:

*:匹配所有字符…:一般用于匹配多个包,多个参数+:表示类及其子类

举例 1:对 aop.annotation.Student 类里面的 eat方法进行增强 execution(public void aop.annotation.Student.eat(…))
举例 2:对 aop.annotation.Student 类里面的所有的方法进行增强 execution(* aop.annotation.Student.* (…))
举例 3:对 aop.annotation 包里面所有类,类里面所有方法进行增强 execution(* aop.annotation.. (…))

3.代码示例:

StudentProxy类:

@Component
@Aspect
public class StudentProxy {
     
    
    //前置通知
    @Before(value = "execution(public void aop.annotation.Student.eat(..))")
    public void beforeDemo(){
     
        System.out.println("饿了!");
    }

    //后置通知(返回通知)
    @AfterReturning("execution(* aop.annotation.Student.*(..))")
    public void afterReturningDemo(){
     
        System.out.println("饭后甜点");
    }

    //最终通知
    @After(value = "execution(void aop.annotation.Student.eat(..))")
    public void afterDemo(){
     
        System.out.println("饱了!");
    }

    //异常通知
    @AfterThrowing("execution(void aop.annotation.Student.eat(..))")
    public void afterThrowingDemo(){
     
        System.out.println("噎住了!");
    }

    //环绕通知
    @Around("execution(* aop.annotation.Student.*(..))")
    public void aroundDemo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
     
        System.out.println("吃饭前...");

        //被增强的方法执行
        proceedingJoinPoint.proceed();

        System.out.println("吃饭后...");

    }

}

Student类:

@Component
public class Student {
      
    public void eat(){
      
        System.out.println("eat something!");
    }
}

xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--开启注解扫描-->
    <context:component-scan base-package="aop.annotation"></context:component-scan>

    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

测试类:

public class DemoTest {
        
    @Test
    public void test1(){
        
        ApplicationContext context = new ClassPathXmlApplicationContext("aop/annotation/bean.xml");

        Student student = context.getBean("student", Student.class);

        student.eat();
    }
}

输出结果:

吃饭前... 饿了! eat something! 饭后甜点 饱了! 吃饭后... Process finished with exit code 0 

更改Student中代码,让其报错,如下:

@Component public class Student {
           public void eat(){
           int i = 1/0; System.out.println("eat something!"); } } 

输出结果:
在这里插入图片描述

4.相同切入点抽取

pointDemo方法上使用@Pointcut注解,把上述代码中的前置通知的切入点表达式用pointDemo方法替换;
同理其他的切入点表达式都可以用其替换,方便开发。

 //相同切入点抽取 @Pointcut(value = "execution(* aop.annotation.Student.eat(..))") public void pointDemo(){
            } //前置通知 @Before(value = "pointDemo()") public void beforeDemo(){
            System.out.println("饿了!"); } 

5.@Order(数字类型值)注解

当有多个增强类对同一个方法进行增强时,可以使用@Order(数字类型值)注解来进行优先级设置,数字类型值越小,优先级越高,越优先执行。
在创建一个StudentOneProxy类对Student类中对eat方法进行增强,设置@Order(2),StudentOneProxy如下:

@Component @Aspect @Order(2) public class StudentOneProxy {
             @Before("execution(* aop.annotation.Student.eat(..))") public void BeforeDemo(){
             System.out.println("StudentOneProxy.BeforeDemo..."); } @Around("execution(* aop.annotation.Student.eat(..))") public void aroundDemo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
             System.out.println("StudentOneProxy.Around..."); proceedingJoinPoint.proceed(); System.out.println("StudentOneProxy.Around..."); } } 

在StudentProxy类上添加@Order(1)注解,截图如下:
在这里插入图片描述
输出结果:

吃饭前... 饿了! StudentOneProxy.Around... StudentOneProxy.BeforeDemo... eat something! StudentOneProxy.Around... 饭后甜点 饱了! 吃饭后... Process finished with exit code 0 

可以看到设置为@Order(1)的Student类先执行。

目录
相关文章
|
1月前
|
Java 编译器 Spring
Spring AOP 和 AspectJ 的区别
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。‌
66 2
|
3月前
|
XML Java 数据库
Spring5入门到实战------10、操作术语解释--Aspectj注解开发实例。AOP切面编程的实际应用
这篇文章是Spring5框架的实战教程,详细解释了AOP的关键术语,包括连接点、切入点、通知、切面,并展示了如何使用AspectJ注解来开发AOP实例,包括切入点表达式的编写、增强方法的配置、代理对象的创建和优先级设置,以及如何通过注解方式实现完全的AOP配置。
|
4月前
|
XML 监控 Java
Java中的AOP编程:AspectJ与Spring AOP的应用
Java中的AOP编程:AspectJ与Spring AOP的应用
|
5月前
|
Java 编译器 Maven
Java一分钟之-AspectJ:AOP库
【6月更文挑战第13天】AspectJ是Java的AOP框架,扩展了语言并提供编译时和加载时织入,便于模块化横切关注点。关键概念包括编织、切面、切点和通知。常见问题涉及编译时织入配置、切点表达式误用、异常处理和版本兼容性。通过正确配置构建工具、精准设计切点、妥善处理异常和确保版本兼容,可避免这些问题。文中还提供了一个记录服务层方法执行时间的代码示例,帮助读者快速上手AspectJ。
155 2
|
5月前
|
XML Java 数据格式
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
51 0
|
5月前
|
监控 Java 数据安全/隐私保护
使用 AOP 记录操作日志
使用 AOP 记录操作日志
57 0
|
6月前
|
Java 开发者 Spring
Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
【5月更文挑战第1天】Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
70 5
|
6月前
|
监控 JavaScript Java
|
6月前
|
存储 关系型数据库 MySQL
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
|
6月前
|
Java
SpringBoot整合AOP整合aspectj实现面向切面编程实现参数接收和请求时间打印
SpringBoot整合AOP整合aspectj实现面向切面编程实现参数接收和请求时间打印
29 0