文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【Spring】面向切面编程详解(AOP)

2023-08-30 13:10

关注

🌕博客x主页:己不由心王道长🌕!
🌎文章说明:spring🌎
✅系列专栏:spring
🌴本篇内容:对面向切面编程即AOP进行一个详细讲解(对所需知识点进行选择阅读呀~)🌴
☕️每日一语:在人生的道路上,即使一切都失去了,只要一息尚存,你就没有丝毫理由绝望。因为失去的一切,又可能在新的层次上复得。☕️
🕤作者详情:作者是一名双非大三在校生,喜欢Java,欢迎大家探讨学习,喜欢的话请给博主一个三连鼓励。🕤

一、AOP概述

什么是AOP

AOP(Aspect Oriented Program)即面向切面编程。我们先回顾以下三层架构,三层架构式垂直架构,即一层对另一层提供服务,不能越级访问,分级进行运作。
在这里插入图片描述
上述架构是垂直分布的,而面向切面则是一个切面:
到底是什么切面呢?
就是把各种类中冗余的代码提取出来,在需要用的时候就横向切入,就像一个切面一样。
到底是什么冗余代码呢?事务处理、异常处理等等!突然来一大堆听不懂。
举个栗子:
在这里插入图片描述

比如说事务控制,在我们的业务中,虽然查询是最多的,但是添加、修改、删除也不少。查询不用提交事务,而后面的都得提交事务,在JDBC中,我们一般都手动提交事务。
在这里插入图片描述
都得提交事务,难道要在调用每一个方法执行完之后都编写一段提交事务的代码吗?这当然可以,不过太傻了!

④解决办法
上面看到了事务提交每次都编写代码会造成代码冗余,复用性不好,也不利于维护(事务提交与代码耦合死了)。
这是我们可以把上面重复的代码提取出来,制成一个切面,需要用的地方就声明它

⑤ 实现先行剧透:通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。

AOP应用场景

日志记录、性能统计、安全控制、事务处理、异常处理

二、AOP的基本术语

术语介绍

Joint point(连接点): 连接点就是可以被拦截的点,在程序中,通常指的是方法,在Spring中只支持方法类型的连接点。在其他的地方可能支持类,这里记住方法就行了。
Pointcut(切点): 切入点就是对连接点中哪些点进行拦截的定义,对连接点(一般所有方法都可做连接点)进行条件筛选。
Advice(通知/增强): 通知就是我们拦截到切点之后,对它做的事情叫做通知或者增强,比如上面的事务,我们拦截到addUser之后,要对它增强,使其在完成方法之后增强提交事务,异常的时候发生回滚。
Aspect(切面): 即切入点和通知的结合(多个切入点共有一个通知,连在一起像不像一个面?)
Weaving(织入): 指的是在把增强的方法加入到目标对象(切点方法的拥有者)来创建新的对象的过程,spring采用的是动态代理织入(jdk动态代理和子类动态代理都有),AspectJ采用编译期织入和类装载织入。

术语举例详解

先说一个故事吧:
有一天,小吉和他的小伙伴(连接点)去后山的山洞冒险,发现山洞里有一个shiti,小吉和其他一部分小伙伴(切点)就把这个shiti抬了出去,回家后其他抬了的小伙伴都die了,这时候小吉的身上开始发绿,爷爷看到就说:“不好,是绿shi寒警告”。

Joint point(连接点): 在上面的故事里,小吉和他的伙伴都能够被绿,就是都能被增强,可以看到绿shi寒警告是可以作用在上面所以人的身上。在Spring中,这些人就等于可以被增强的方法。
Pointcut(切点): 在上面的故事里,只有小吉和其他几名抬了这个东西的小伙伴收到了绿shi寒,其他没有抬的小伙伴则没有事。可以看出来Pointcut(切点)是有条件的Joint point(连接点),抬了的人被增强了。
Advice(通知/增强): 上面的小伙伴在抬了以后,那个东西就对他们进行了增强。
Aspect(切面): 切点和通知的结合,上面的切点就是抬了的小伙伴和小吉,通知是抬之后的作用,切点有很多,连载一起就像一个面一样。

三、AOP实例说明

一、创建maven工程
二、导入相关配置文件

<dependencies>        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>5.2.5.RELEASE</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-core</artifactId>            <version>5.2.5.RELEASE</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-aop</artifactId>            <version>5.2.5.RELEASE</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->        <dependency>            <groupId>org.aspectj</groupId>            <artifactId>aspectjweaver</artifactId>            <version>1.9.6</version>            <scope>runtime</scope>        </dependency>

三、添加applicationContext.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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

注意、上面给了Aop的命名空间。

四、定义接口和实现类
这里的实现类里面定义的方法就是连接点,至于要增强哪个方法,由程序员根据自己的业务要求,自己指定,要增强的方法就是切点
在这里插入图片描述

package com.bipt.ServiceAop;public interface UserService {    public void save();    public void addUser();}package com.bipt.ServiceAop.impl;import com.bipt.ServiceAop.UserService;public class ImplUserService implements UserService {    @Override    public void save() {        System.out.println("save......");    }    @Override    public void addUser() {        System.out.println("AddUser.......");    }}

在Spring配置文件中添加bean,把ImplUserService作为连接点
在这里插入图片描述

四、写通知类和在配置文件中引入

package com.bipt.ServiceAop;public class MyAdvice {    public void advice1(){        System.out.println("吉尼抬没?");    }}

在这里插入图片描述

五、定义切入点和制作切面

<aop:config>        <!--配置切点,即在哪些方法用到增强,后面是表达式-->        <aop:pointcut id="mypointCut" expression="execution( void com.bipt.ServiceAop.impl.ImplUserService.save())"/>        <!--配置切面,切面就是通知加上增强-->        <aop:aspect id="myadvice" ref="Advice">            <!--before表示前置通知,在切点执行之前执行,method则是通知里的一种方法-->            <aop:before method="advice1" pointcut-ref="mypointCut"></aop:before>        </aop:aspect>    </aop:config>

六、测试
测试要先导入测试的依赖,这里不用Spring的依赖,用junit。

 <!-- https://mvnrepository.com/artifact/junit/junit -->        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.12</version>            <scope>test</scope>

然后编写测试类

package com.bipt;import com.bipt.ServiceAop.UserService;import com.bipt.ServiceAop.impl.ImplUserService;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import javax.annotation.processing.SupportedAnnotationTypes;public class MyTest {    @Test    public void AopTest(){        ApplicationContext App = new ClassPathXmlApplicationContext("applicationContext.xml");        UserService userService = (UserService) App.getBean("JointPoint");        userService.save();    }}

测试结果如下:
在这里插入图片描述
可以看到结果正确,我们完成了一个入门测试,至于为什么通知在切入点之前执行是因为我们在上面配置切面的时候使用的是before,即前置增强。

四、通知类型详解

概述

通知类型大致分为六类: 分别是前置通知、后置通知、环绕通知、最终通知、异常抛出通知和引介通知。
上述通知中的引介通知我们是用不到的,这里不做介绍。

前置通知

即before,在上面的例子中我们可以清楚的看到,前置通知在切入点方法执行之前执行了。这就是前置通知的作用范围。前置通知的方式一把也可以用作权限验证。

后置通知

即after—running 在目标方法执行之后执行

<aop:pointcut id="after" expression="execution(* com.bipt.ServiceAop.impl.ImplUserService.save())"/>        <!--配置切面,切面就是通知加上增强-->        <aop:aspect  ref="Advice">            <!--before表示后置通知,在切点执行之前执行,method则是通知里的一种方法--><!--            <aop:around method="advice2" pointcut-ref="mypointCut2" ></aop:around>-->            <!--后置通知-->            <aop:after-returning method="after_running" pointcut-ref="after" />

在这里插入图片描述

环绕通知

环绕通知是重点,是最重要的一个通知。环绕通知功能比较强大,它可以追加功能到方法执行的前后,这也是比较常用的方式,它可以实现其他四种通知类型的功能。
环绕通知的怎么做到在方法执行前后追加功能呢? 不难,做一个演示
在这里插入图片描述

最终通知

即after。不管前面发生什么,最终通知都会执行。这里进行演示

<aop:aspect id="myadvice" ref="Advice">            <!--before表示后置通知,在切点执行之前执行,method则是通知里的一种方法-->            <aop:after method="advice1" pointcut-ref="mypointCut"></aop:after>        </aop:aspect>

结果:
在这里插入图片描述
可以看到两个方法执行循序与前置通知相反了。

六、AOP实现声明式事务

二、添加事务管理

事务分为声明式事务和编程式事务,编程式事务就是JDBC的事务提交、回滚等等,这样不太方便,我们有很多的方法都要用到事务,不能需要一个就编写一个,这样太重复了。我们可以把事务抽取出来,利用Spring提高的声明式事务管理来处理。
Spring声明式事务是基于AOP(面向切面)实现的
① 配置事务管理器
事务管理器有很多种,不同的数据访问层框架有不同的实现,而Mybatis的事务管理器为:DataSourceTransactionManager
在这里插入图片描述
②配置事务增强/通知(Advice)
在这里插入图片描述
③ 配置切面
在这里插入图片描述

配置代码:

<?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:tx="http://www.springframework.org/schema/tx"       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/tx  http://www.springframework.org/schema/tx/spring-tx.xsd        http://www.springframework.org/schema/aop expression="com.bipt.controller"/>    </context:component-scan>    <!--导入配置文件-->    <context:property-placeholder location=" classpath:config.properties"></context:property-placeholder>    <!--配置数据源-->    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">        <property name="driverClassName" value="${jdbc.driver}">    </bean>    <!--配置事务管理器-->    <bean id="transactionManager" class="    org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="dataSource"></property>    </bean>    <!--配置事务增强-->    <tx:advice id="transactionAdvice" transaction-manager="transactionManager">        <tx:attributes>            <tx:method name="login*"  read-only="true"/>            <tx:method name="register*" propagation="REQUIRED" rollback-for="Exception,RuntimeException" read-only="false"/>        </tx:attributes>    </tx:advice>    <!--配置切面-->    <aop:config>        <aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut"></aop:advisor>        <aop:aspect ref="dataSource">            <aop:pointcut id="transactionPointcut" expression="execution(* com.bipt.service.*.*(..)) "/>        </aop:aspect>    </aop:config></beans>

结语

码字不易、觉得有帮助的小伙伴动动小手给个三连,无比感谢。

来源地址:https://blog.csdn.net/qq_63992577/article/details/127353729

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-人工智能
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯