Spring AOP简介及相关案例
作者:mmseoamin日期:2024-03-20

目录

一、Spring AOP简介

二、AOP相关术语

三、AOP入门案例

1. 引入依赖

2. 编写连接点

3. 编写通知

4. 配置切面

5. 测试 

四、通知类型

1. 编写通知方法

2. 配置切面

3. 测试

五、切点表达式

六、多切面配置 

1. 编写发送邮件的通知

2. 配置切面

3. 测试 

往期专栏&文章相关导读 

1. Maven系列专栏文章

2. Mybatis系列专栏文章

3. Spring系列专栏文章 


一、Spring AOP简介

        AOP的全称是Aspect Oriented Programming,即面向切面编程。是实现功能统一维护的一种技术,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。

  • 作用:在不修改源码的基础上,对已有方法进行增强。实现原理:动态代理技术。
  • 优势:减少重复代码、提高开发效率、维护方便
  • 应用场景:事务处理、日志管理、权限控制、异常处理等方面。

二、AOP相关术语

Spring AOP简介及相关案例,第1张

 为了更好地理解AOP,就需要对AOP的相关术语有一些了解

名称 说明
Joinpoint(连接点)指能被拦截到的点,在Spring中只有方法能被拦截。
Pointcut(切点)指要对哪些连接点进行拦截,即被增强的方法。
Advice(通知)指拦截后要做的事情,即切点被拦截后执行的方法。
Aspect(切面)切点+通知称为切面
Target(目标)被代理的对象
Proxy(代理)代理对象
Weaving(织入)生成代理对象的过程

三、AOP入门案例

AspectJ是一个基于Java语言的AOP框架,在Spring框架中建议使用AspectJ实现AOP。

接下来我们写一个AOP入门案例:dao层的每个方法结束后都可以打印一条日志:

1. 引入依赖

    
        
            org.springframework
            spring-context
            5.3.13
        
        
            junit
            junit
            4.12
            test
        
        
            mysql
            mysql-connector-java
            8.0.27
        
    

2. 编写连接点

package com.example.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
    public void add(){
        System.out.println("用户新增");
    }
    public void delete(){
        System.out.println("用户删除");
    }
    public void update(){
        System.out.println("用户修改");
    }
}

3. 编写通知类

package com.example.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
public class MyAspectJAdvice {
    // 后置通知
    public void myAfterReturning(JoinPoint joinPoint){
        System.out.println("切点方法名:"+joinPoint.getSignature().getName());
        System.out.println("目标对象:"+joinPoint.getTarget());
        System.out.println("打印日志···"+joinPoint.getSignature().getName()+"方法被执行了!");    }
}

4. 配置切面

bean.xml文件



        
        
        
        
        
        
            
            
                
                
                
                
            
        
  

5. 测试 

import com.example.SpringConfig;
import com.example.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserDaoTest {
    @Test
    public void testAdd(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        UserDao userDao = (UserDao) ac.getBean("userDao");
        userDao.add();
    }
    @Test
    public void testDelete(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        UserDao userDao = (UserDao) ac.getBean("userDao");
        userDao.delete();
    }
}

运行结果分别为

Spring AOP简介及相关案例,第2张

 Spring AOP简介及相关案例,第3张

Spring AOP简介及相关案例,第4张  

OK,确实是可以的,本次入门案例就学习到这里了。 

四、通知类型

 AOP有以下几种常用的通知类型:

通知类型描述
前置通知在方法执行前添加功能
后置通知在方法正常执行后添加功能
异常通知在方法抛出异常后添加功能
最终通知无论方法是否抛出异常,都会执行该通知
环绕通知在方法执行前后添加功能

1. 编写通知方法

    // 前置通知
    public void myBefore(){
        System.out.println("前置通知···");
    }
    // 异常通知
    public void myAfterThrowing(Exception e){
        System.out.println("异常通知···");
        System.out.println(e.getMessage());
    }
    // 最终通知
    public void myAfter(){
        System.out.println("最终通知···");
    }
    // 环绕通知
    public Object myAround(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕前···");
        // 执行方法
        Object obj = point.proceed();
        System.out.println("环绕后···");
        return obj;
    }

2. 配置切面

        
        
            
            
                
                
                
                
                
                
                
                
                
                
                
                
            
        

3. 测试

OK,这里我们测试用户新增方法 ,确实是得出来我们想要的结果了

Spring AOP简介及相关案例,第5张

五、切点表达式

切点表达式:访问修饰符 返回值 包名.类名.方法名(参数列表)

  • 使用AspectJ需要使用切点表达式配置切点位置,写法如下:
  • 标准写法:访问修饰符 返回值 包名.类名.方法名(参数列表)
  • 访问修饰符可以省略。
  • 返回值使用 * 代表任意类型。
  • 包名使用 * 表示任意包,多级包结构要写多个 * ,使用 *.. 表示任意包结构
  • 类名和方法名都可以用 * 实现通配。

    参数列表

    • 基本数据类型直接写类型
    • 引用类型写 包名.类名
    • * 表示匹配一个任意类型参数
    • .. 表示匹配任意类型任意个数的参数

      全通配: * *..*.*(..)

六、多切面配置 

        我们可以为切点配置多个通知,形成多切面,比如希望dao层的每个方法结束后都可以打印日志并发送邮件:

1. 编写发送邮件的通知

package com.example.aspect;
import org.aspectj.lang.JoinPoint;
public class MyAspectJAdvice2 {
    // 后置通知
    public void myAfterReturning(JoinPoint point){
        System.out.println("发送邮件···");
    }
}

2. 配置切面

在上面的基础上配置多一个切面即可

    
         
         
    

3. 测试 

Spring AOP简介及相关案例,第6张

        OK,确实是打印了发送邮件,因此该多切面配置成功,下面接着讲解用另外几种方法实现AOP ,让我们一起学习啪

往期专栏&文章相关导读 

     大家如果对于本期内容有什么不了解的话也可以去看看往期的内容,下面列出了博主往期精心制作的Maven,Mybatis等专栏系列文章,走过路过不要错过哎!如果对您有所帮助的话就点点赞,收藏一下啪。其中Spring专栏有些正在更,所以无法查看,但是当博主全部更完之后就可以看啦。

1. Maven系列专栏文章

Maven系列专栏Maven工程开发
Maven聚合开发【实例详解---5555字】

2. Mybatis系列专栏文章

Mybatis系列专栏MyBatis入门配置
Mybatis入门案例【超详细】
MyBatis配置文件 —— 相关标签详解
Mybatis模糊查询——三种定义参数方法和聚合查询、主键回填
Mybatis动态SQL查询 --(附实战案例--8888个字--88质量分)
Mybatis分页查询——四种传参方式
Mybatis一级缓存和二级缓存(带测试方法)
Mybatis分解式查询
Mybatis关联查询【附实战案例】
MyBatis注解开发---实现增删查改和动态SQL
MyBatis注解开发---实现自定义映射关系和关联查询

3. Spring系列专栏文章 

Spring系列专栏Spring IOC 入门简介【自定义容器实例】
IOC使用Spring实现附实例详解
Spring IOC之对象的创建方式、策略及销毁时机和生命周期且获取方式
Spring DI简介及依赖注入方式和依赖注入类型
Spring IOC相关注解运用——上篇
Spring IOC相关注解运用——下篇
Spring AOP简介及相关案例
注解、原生Spring、SchemaBased三种方式实现AOP【附详细案例】
Spring事务简介及相关案例
Spring 事务管理方案和事务管理器及事务控制的API
Spring 事务的相关配置、传播行为、隔离级别及注解配置声明式事务