【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理

这篇具有很好参考价值的文章主要介绍了【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、认识SpringAOP

1、AOP是什么?

2、AOP的功能

3、AOP的组成(重要)

二、SpringAOP的实现

🌷1、添加Spring AOP框架支持

🌷2、定义切面和切点

🌷 3、定义通知

3.1 完成代码实现

3.2 具体通知分析

🌷4、小练习:使用AOP统计UserController每个方法的执行时间。

 三、SpringAOP的实现原理(重点)


一、认识SpringAOP

🌷1、AOP是什么?

        AOP是一个思想Spring AOP 是⼀个框架,是对 AOP 思想的实现,它们的关系和IoC 与 DI 类似。OOP是面向对象编程。AOP:面向切面编程:对某一类事情的集中处理(也就是同一类的事务怎么处理)。

栗子:

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

        比如CSDN:编辑博客,删除博客,写博客都要在用户登录的基础上实现,所以在都实现单个的功能之前,都要对用户登录信息进行验证,各自实现或者调用用户验证的方法,所以非常麻烦。那么抽取成一个公共方法也可以:但是当对公共方法的参数或者其他进行了修改,那么它的所有调用方都要进行修改。所以对于这种功能统⼀,且使⽤的地⽅较多的功能,就可以考虑 AOP来统⼀处理了。所以现在AOP就是:这是哪个功能都要实现的是相同的功能,我们可以将它理解为就是对一类事情的集中处理,现在只需要在某一处配置一下就好了,此时所有需要时判断用户登录的方法就可以全部实现用户登录验证了。

🌷2、AOP的功能

(1)统⼀⽇志记录
(2)统⼀⽅法执⾏时间统计:项目监控、监控项目请求流量、监控接口的响应时间,甚至每个方法的响应时间;
(3)统⼀的返回格式设置:http状态码、code(业务状态码:后端处理响应成功,不代表业务办理成功)、msg(业务处理失败,返回的信息)、data;
(4)统⼀的异常处理;
(5)事务的开启和提交等。【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java


注意:使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object Oriented Programming,⾯向对象编程)的补充和完善

 🌷3、AOP的组成(重要)

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

        比如我们上面举的例子:关于csdn的博客的整个过程就是一个切面:其中:写博客功能、删除博客、编辑博客都是连接点,它们三个都要实现一个用户登录功能的校验,这个用户登录功能就是一个切点,其中用户登录功能中的方法体中实现代码就是一个通知。

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java


二、SpringAOP的实现(重要)

目标:我们就实现上图中的关于csdn的博客的这个AOP的实现。我们使用SpringAOP来实现AOP的功能,目的是拦截所有UserController方法,每次调用UerController中的任何一个方法的时候,都执行相应的通知事件。

SpringAOP的实现步骤如下:

(1)添加SpringAOP的框架支持;

(2)定义切面和切点;

(3)定义通知。

🌷1、添加Spring AOP框架支持

在 pom.xml 中添加如下配置:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

🌷2、定义切面和切点

//表示是一个切面:CSDN
@Component
@Slf4j
//表示是一个切面:CSDN,要结合五大注解使用
@Aspect
public class LoginAspect {
    //表示是一个切点:登录功能验证
    @Pointcut("execution(* aop.controller.UserController.*(..))")
    public void pointcut1(){
        //方法体就是通知
    }
}

🍑总结 :

        切点指的是具体要处理的某一类问题:用户登录权限的验证就是一个具体的问题,也就是一个切点。

(1)切面上要加@Aspect注解,结合五大注解使用:加@Component;

(2)切点: pointcut 方法为空方法,它不需要有方法体,此方法名就是起到⼀个“标识”的作用,标识下面的通知方法具体指的是哪个切点(因为切点可能有很多个)。

(3)一个@Aspect(切面)下可以有多个切点,@Pointcut("execution(* aop.controller.UserController.*(..))")。同时通知方法不是一定要全部存在的。

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

(4)切点表达式由切点函数组成,其中 execution() 是最常用的切点函数,用来匹配方法,语法为
execution(<修饰符><返回类型><包.类.方法(参数)><异常>)

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

切点表达式说明:

(1)灰色表示可以省略,红色不能省略;

(2)修饰符是public等,其中*表示任意;

(3)返回值:*表示任意;

(4)包名:

com.example       表示固定包

com.example.*.service   表示example包下任意包下的固定目录service

com.example..     表示example包下所有的子包(含自己)

com.example.*.service..   表示example包下任意子包下固定目录service下的任意包。

(5)类

UserController   表示指定类

*Impl     表示以Impl结尾

User*    表示以User开头

*      表示任意

(6)方法名

writeBlog  固定方法

write*  表示以write开头

*Blog   表示以Blog结尾

* 表示任意

(7)参数

()  表示无参

(int)表示一个整型

(int,int)表示两个整型

(..)表示参数任意

(8)异常:throws一般不写

AspectJ ⽀持三种通配符
(1)* 表示匹配任意字符,只匹配⼀个元素(包,类,或⽅法,⽅法参数)
(2).. 表示匹配任意字符,可以匹配多个元素 ,在表示类时,必须和 * 联合使⽤。
(3)+ 表示表示按照类型匹配指定类的所有类,必须跟在类名后⾯,如 com.cad.Car+ ,表示继承该类的所有⼦类包括本身。


比如:

execution(* com.cad.demo.User.*(..)) :匹配 User 类里的所有方法。
execution(* com.cad.demo.User+.*(..)) :匹配该类的子类包括该类的所有方法。
execution(* com.cad.*.*(..)) :匹配 com.cad 包下的所有类的所有方法。
execution(* com.cad..*.*(..)) :匹配 com.cad 包下、方法包下所有类的所有⽅法。
execution(* addUser(String, int)) :匹配 addUser 方法,且第⼀个参数类型是 String,第⼆个参数类型是 int。

🌷 3、定义通知

通知定义的是被拦截的方法(具体的写博客、编辑博客和删除博客)具体要执行的业务(用户登录权限的校验)。
使用以下注解,会设置方法为通知方法,在满足条件后会通知本方法进行调用:
(1)前置通知使用@Before:通知方法会在目标方法调用之前执行。
(2)后置通知使用@After:通知方法会在目标方法返回或者抛出异常后调用。
(3)返回之后通知使用@AfterReturning:通知方法会在目标方法返回后调用。
(4)抛异常后通知使用@AfterThrowing:通知方法会在目标方法抛出异常后调用。
(5)环绕通知使用@Around:通知包裹了被通知的方法,在被通知的方法通知之前和调用之后执行自定义的行为。

3.1 完成代码实现

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

UserController文件

@Slf4j
@RequestMapping("/aop")
@RestController
public class UserController {
    //模拟写博客
    @RequestMapping("/writeBlog")
    public String writeBlog(){
        //模拟异常
//        int a = 10/0;
        log.info("write blog success...");
        return "write blog success...";
    }
    //编辑博客
    @RequestMapping("/editBlog")
    public String editBlog(){
        log.info("edit blog success...");
        return "edit blog success...";
    }
    //删除博客
    @RequestMapping("/deleteBlog")
    public String deleteBlog(){
        log.info("deleteBlog success...");
        return "deleteBlog success...";
    }
}

 LoginAspect文件


@Component
@Slf4j
//表示是一个切面:CSDN,要结合五大注解使用
@Aspect
public class LoginAspect {
    //表示是一个切点:登录功能验证
    @Pointcut("execution(* aop.controller.UserController.*(..))")
    public void pointcut1(){ }
    //1、前置通知使用@Before:通知方法会在目标方法调用之前执行。
    @Before("pointcut1()")
    public void doBefore(){
        log.info("do before...");
    }
    //2、后置函数@After
    @After("pointcut1()")
    public void doAfter(){
        log.info("do After...");
    }

    //3、@AfterReturning 在return 之前通知
    @AfterReturning("pointcut1()")
    public void doAfterReturning(){
        log.info("do doAfterReturning...");
    }

    //4、@doAfterThrowing 在return 之前通知
    @AfterThrowing("pointcut1()")
    public void doAfterThrowing(){
        log.info("do doAfterThrowing...");
    }

    //5、@doAround 环绕方法
    @Around("pointcut1()")
    //环绕方法要写返回结果  //ProceedingJoinPoint joinPoint表示连接点
    public Object doAround(ProceedingJoinPoint joinPoint){
        Object object = null;
        log.info("环绕通知执行之前执行的方法...");
        //执行目标方法
        try {
            object = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        log.info("环绕通知执行之后执行的方法...");
        return object;
    }


    @Pointcut("execution(* aop.controller.UserController1.*(..))")
        public void pointcut2(){ }
}

3.2 具体通知分析

(1)@Before

@Before在具体的目标方法调用之前执行。

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

测试UserController类中的三个方法都成功:比如 【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

 2、@After

@After在具体调用目标方法之后执行;

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

(3)@AfterReturing

使用@AfterReturing会在目标方法return之前通知,知道@AfterReturing在@After之前执行;

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

(4)@AfterThrowing

🍑总结

         @doAfterThrowing只有在异常的时候才会执行,正常返回不会执行。异常情况@doAfterThrowing执行之后,@doAfterReturning就不会执行了。正常返回的时候执行@doAfterReturning,出现异常就不会执行了。

正常情况:

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

 异常情况:

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

(5)@Around(最常用)

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

🍑注意:

        先执行环绕通知,再执行前置通知,接着是目标方法,然后是doAfterReturing和do After后置通知。

  • getSignature()) //获取修饰符+ 包名+组件名(类名) +方法名
  • getSignature().getName()) //获取方法名
  • getSignature().getDeclaringTypeName()) //获取包名+组件名(类名)

🌷4、小练习:使用AOP统计UserController每个方法的执行时间。

普通写法:

在UserController中的每个方法都按如下计算:缺点是所有的方法(包括writeBlog,editBlog方法)都要写一下,冗余性很高。

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

AOP的写法

 /**
     * 计算UserController中所有方法的Log的执行时间
     */
    //表示是一个切点:登录功能验证
    @Pointcut("execution(* aop.controller.UserController.*(..))")
    public void pointcut2(){ }
    //@doAround 环绕方法
    @Around("pointcut2()")
    //环绕方法要写返回结果
    public Object doAround(ProceedingJoinPoint joinPoint){
        Object object = null;
        long start = System.currentTimeMillis();
        //执行目标方法
        try {
            object = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        //getSignature()) //获取修饰符+ 包名+组件名(类名) +方法名
        log.info(joinPoint.getSignature().toLongString()+"耗时"+(System.currentTimeMillis()-start));
        return object;
    }

测试结果:

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

 时间不同主要是cpu调度的偏差。


 三、SpringAOP的实现原理(重点)

简单了解代理模式~https://mp.csdn.net/mp_blog/creation/editor/131963215

【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java

🍑总结:

(1)SpringAOP是构建在动态代理的基础上,所以Spring对AOP的支持局限于方法级别的拦截。

(2)Spring AOP支持JDK Proxy和 CGLIB的方式实现动态代理;

(3)proxyTargetClass为false,目标实现了接口,AOP默认会基于JDK的方式生成代理类;

(4)proxyTargetClass为false,没有实现接口的类,AOP会基于CGLIB的方式生成代理类;

(5)proxyTargetClass为false为true,AOP会基于CGLIB的方式生成代理类。


【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理,Spring学习,spring,学习,java文章来源地址https://www.toymoban.com/news/detail-614339.html

到了这里,关于【Spring AOP学习】AOP的组成 && SpringAOP的实现和实现原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring AOP实现原理

    从入口  org.springframework.context.support.AbstractApplicationContext#refresh  开始看 找到Bean的创建方法进入: 再进入详细方法:  找到getBean(beanName): 找到doGetBean(xxx,xxx,xxx,xxx);   找到实际的Bean创建方法createBean(beanName, mdb, args);可以非常明显的看到,Bean就是通过Proxy的方式获取的。   继续

    2023年04月25日
    浏览(32)
  • Spring AOP的原理与实现

    前言: 博主在最近的几次面试中,大中小厂都问到了Spring的AOP思想相关问题,这块知识确实是面试中的重点内容,因此结合所看的书籍,在这篇文章中总结下。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读,感谢大佬的关注。 如果文章有什么需要改进的地方欢迎

    2024年02月13日
    浏览(26)
  • Spring AOP 实现原理和使用场景

    Spring AOP 是通过在目标方法执行前、执行后、抛出异常时等切入点执行切面代码的一种机制。其实现原理是使用动态代理技术,在方法运行时动态生成代理对象,然后插入切面代码。当执行目标方法时,由动态代理对象拦截方法并在适当的时间点执行切面代码,然后再调用实

    2024年02月05日
    浏览(45)
  • 【Java学习】 Spring的基础理解 IOC、AOP以及事务

        官网: https://spring.io/projects/spring-framework#overview     官方下载工具: https://repo.spring.io/release/org/springframework/spring/     github下载: https://github.com/spring-projects/spring-framework     maven依赖: 1.spring全家桶的结构构图:              最下边的是测试单元   其中spring封装

    2024年02月09日
    浏览(29)
  • JAVA:使用 Spring AOP 实现面向切面编程

    1、简述 在现代的软件开发中,面向切面编程(AOP)是一种重要的编程范式,它允许我们将横切关注点(如日志记录、性能监控、事务管理等)从应用程序的核心业务逻辑中分离出来,以提高代码的模块化和可维护性。Spring 框架提供了强大的 AOP 支持,使得我们可以轻松地实

    2024年04月13日
    浏览(33)
  • Java实战:Spring Boot实现AOP记录操作日志

    本文将详细介绍如何在Spring Boot应用程序中使用Aspect Oriented Programming(AOP)来实现记录操作日志的功能。我们将探讨Spring Boot集成AOP的基本概念,以及如何使用Spring Boot实现AOP记录操作日志。最后,我们将通过一个具体示例来演示整个实现过程。本文适合已经具备Spring Boot基础

    2024年02月22日
    浏览(41)
  • Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

    开篇: 欢迎再次来到 Spring 5 学习系列!在这个博客中,我们将深入研究 Spring 框架的AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式)。 概念 什么是AOP (1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的

    2024年01月24日
    浏览(37)
  • Spring Boot学习随笔- 实现AOP(JoinPoint、ProceedingJoinPoint、自定义注解类实现切面)

    学习视频:【编程不良人】2021年SpringBoot最新最全教程 问题 现有业务层开发存在问题 额外功能代码存在大量冗余 每个方法都需要书写一遍额外功能代码不利于项目维护 Spring中的AOP AOP:Aspect 切面 + Oriented 面向 Programmaing 面向切面编程 Aspect(切面) = Advice(通知) + Pointcut(

    2024年02月04日
    浏览(33)
  • Spring Aop原理

    AOP:将那些与业务无关,却与业务模块所共同调用的逻辑(例如事务处理,日志管理,权限管理等) 封装成一个可重用的模块,这个模块被称为\\\"切面\\\",便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。 如上举例所示:         如上图举例所

    2024年01月17日
    浏览(28)
  • 9.spring aop 原理

    环境:spring boot 2.6.13 是对

    2024年01月18日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包