IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring基础学习之AOP面向切面编程 -> 正文阅读

[Java知识库]Spring基础学习之AOP面向切面编程

前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个Spring基础学习系列是用来记录我学习Spring框架基础知识的全过程 (这个系列是参照B站狂神的Spring5最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将会以一天一更的速度更新这个系列,还没有学习Spring5框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。
最后,希望能够和大家一同进步吧!加油吧!少年们!
废话不多说,让我们开始今天的学习内容吧,今天我们来到了Spring基础学习的第十站:AOP面向切面编程

11.AOP 面向切面编程

11.1 AOP概述

11.1.1 什么是AOP?

  • AOP(Aspect Oriented Programming):面向切面编程,通过预编译方式运行期动态代理实现程序功能的统一维护的一种技术
  • AOPOOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型

11.1.2 AOP的优点

  • 利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务人员专心于业务逻辑的处理
  • 使业务逻辑各部分之间的耦合度降低,提高程序的可重用性
  • 提高系统的可维护性,同时提高了开发的效率

AOP面向切面编程结构图

在这里插入图片描述

11.2 AOP在Spring中的作用

11.2.1 AOP相关概念

提供声明式事务即允许用户自定义切面

  • 横切关注点跨越应用程序多个模块的方法或功能 (即与业务逻辑无关的,但是需要关注的部分),这就是横切关注点 (如日志管理,权限控制,事务处理、异常处理等)
  • 切面 (Aspect):横切关注点被模块化的特殊对象 (也就是切入点和通知的结合),即它是一个类 (例如日志类 Log)
  • 通知 (Advice):切面必须要完成的工作 (即对切入点增强的内容),它是类中的一个方法 (日志类Log中的方法,例如前置、后置和环绕通知等)
  • 切入点 (PointCut):是指要对哪些JointPoint进行拦截,即被拦截的连接点 (可以理解为对切面通知执行的"地点"的定义)
  • 连接点 (JointPoint):是指那些被拦截的点,在Spring中,可以使用动态代理拦截目标类的方法 (即与切入点匹配的执行点)
  • 目标 (Target) :是指代理的目标对象 (也就是被通知的对象)
  • 代理(Proxy):是指生成的代理对象 (即向目标对象应用通知之后创建的对象)
  • 织入 (Weaving):是指把增强代码应用到目标上,生成代理对象的过程

11.2.2 AOP实现结构图

在这里插入图片描述

11.2.3 SpringAOP中的Advice

SpringAOP中,通过Advice定义横切逻辑,Spring中支持5中类型的Advice

通知类型作用实现接口应用
前置通知在目标方法执行前实施增强,org.springframework.aop.MethodBeforeAdvice可以应用于权限管理
后置通知在目标方法执行后实施增强org.springframework.aop.AfterReturningAdvice可以用关闭流、上传文件、删除临时文件等功能
环绕通知在目标方法执行前后实施增强org.aopalliance.intercept.MethodInterceptor可以应用于日志、事务管理等功能
异常抛出通知在方法抛出异常后执行通知org.springframework.aop.ThrowsAdvice可以应用于处理异常记录日志等功能
引介通知在目标类中添加一些新的方法和属性org.springframework.aop.IntroductionInterceptor可以应用于老版本程序(增强类)

即AOP在不改变原有代码的情况下,去增加新的功能

11.3 使用Spring实现AOP

11.3.1 使用AOP织入,需要导入一个依赖包

 <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>
  • 方式一使用Spring的API接口【主要SpringAPI接口实现】
  • 方式二自定义来实现AOP【主要是切面定义】

11.3.2 使用Spring的API接口

1.创建Log实体类

//实现前置通知接口的Log实体类
public class Log implements MethodBeforeAdvice {

    /**
     * 前置通知方法
     * @param method:要执行的目标对象的方法
     * @param args:参数
     * @param target:目标读写
     */
    public void before(Method method, Object[] args, Object target) throws Throwable {
    
        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
        
    }
    
}

2.创建AfterLog实体类

// 实现后置通知接口的AfterLog实体类
public class AfterLog implements AfterReturningAdvice {

    // returnValue:返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
    }
    
}

3.创建UserService接口

// 创建用户服务接口(抽象角色)
public interface UserService {

    // 定义增删改查方法
    public void add();
    
    public void delete();
    
    public void update();
    
    public void query();
    
}

4.创建UserService接口实现类

// 用户服务接口的实现类(真实角色)
public class UserServiceImpl implements UserService {

    public void add() {
        System.out.println("增加一个用户");
    }
    
    public void delete() {
        System.out.println("删除一个用户");
    }
    
    public void update() {
        System.out.println("修改加一个用户");
    }
    
    public void query() {
        System.out.println("查询一个用户");
    }
    
}

5.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">
    
    <!-- 注册目标类和切面等bean对象 -->
    <!-- 目标类 -->
    <bean id="userService" class="com.kuang.service.UserServiceImpl"></bean>
    <!-- 切面 -->
    <bean id="log" class="com.kuang.log.Log"></bean>
    <bean id="afterLog" class="com.kuang.log.AfterLog"></bean>
    
    <!-- 方式一:使用原生Spring API接口 -->
    <!-- 配置aop:需要导入aop的约束 -->
    <aop:config>
        <!-- 配置切入点,通知最后增强哪些方法 -->
        <!-- pointcut是指被拦截的连接点,也就是切面通知的执行点 -->
        <!-- expression:使用切面表达式,增强com.kuang.service.UserServiceImpl包下的所有类型的全部方法 -->
        <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
        <!-- 关联通知Advice和切入点pointcut -->
        <!-- 前置通知 -->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <!-- 后置通知 -->
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
    
</beans>

6.创建测试类

public class MyTest {
    public static void main(String[] args) {
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 动态代理的是接口
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
    
}

7.测试结果

在这里插入图片描述

11.3.3 自定义来实现AOP

1.自定义切面类

// 自定义的切面类: 可以存在多个通知Advice (增强的方法内容)
public class DiyPointCut {
    
    // 前置通知
    public void before() {
        System.out.println("======方法执行前======");
    }
    
    // 后置通知
    public void after() {
        System.out.println("======方法执行后======");
    }
    
}

2.创建UserService接口

同11.3.2的UserService接口

3.创建UserService接口实现类

同11.3.2的UserService接口实现类

4.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">
    
    <!-- 注册目标类、切面的bean信息 -->
    <!-- 目标类 -->
    <bean id="userService" class="com.kuang.service.UserServiceImpl"></bean>
    
    <!-- 方式二:自定义类 -->
   <!-- 切面:其实就是被模块化的特殊对象(实际上就是一个类) -->
    <bean id="diy" class="com.kuang.diy.DiyPointCut"/>
     <!-- 配置aop -->
    <aop:config>
        <!-- 引入自定义的切面,ref中是要引用的类 -->
        <aop:aspect ref="diy">
             <!-- 配置切入点,通知最后增强哪些方法 -->
            <!-- pointcut:是指被拦截的连接点,即切面通知执行的地点 -->
            <!-- expression:使用切面表达式,增强com.kuang.service下的指定类UserServiceImpl的所有类型的全部方法 -->
            <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
                <!-- 增强com.kuang.service包及其子包下所有类的所有类型的全部方法 -->
<!--            <aop:pointcut id="point" expression="execution(* com.kuang.service..*.*(..))"/>-->
            <!-- 关联通知Advice和切入点pointCut -->
            <!-- Advice:是指切面必须要完成的工作,对切入点增强的内容(实际上就是类的一个方法) -->
            <!-- 前置通知 -->
            <aop:before method="before" pointcut-ref="point"/>
            <!-- 后置通知 -->
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
    
</beans>

5.创建测试方法

  • 同11.3.2中的测试方法

6.测试结果

在这里插入图片描述

11.3.4 Aspectj切入点语法定义

定义切入点表达式:例如execution(* com.example.service.impl…*. *(…))

execution()是做常用的切点函数,其语法为:整个表达式可以分为五个部分

  • execution()表达式主体

  • 第一个*号表示返回类型, *号表示所有的类型

  • 包名表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.example.service.impl包、子孙包下所有类的方法

  • 第二个*号表示类名, *号表示所有的类

  • *(…)最后这个星号表示方法名, *号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数

总结

简单来说就是,该表达式的作用就是增强该包及其子包下的所有类的所有类型的全部方法

11.3.5 使用注解实现AOP

1.创建AnnotationPointCut实体类

// 方式三:使用注解方式实现AOP
@Aspect
// 标注这个类是个切面
public class AnnotationPointCut {
    
    // 前置通知(切入点表达式)
    @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("====方法执行前====");
    }
    
    // 后置通知(切入点表达式)
    @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("====方法执行后=====");
    }
    
    // 环绕通知
    @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
    // 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
    public void around(ProceedingJoinPoint jp) throws Throwable { // 环绕方法中的参数为连接点
        System.out.println("=====环绕前=====");
        Signature signature = jp.getSignature(); // 获得签名
        System.out.println("签名为:"+signature);
        Object proceed = jp.proceed(); // 执行方法
        System.out.println("=====环绕后=====");
        System.out.println(proceed);
    }
    
}

2.创建UserService接口

  • 同11.3.2UserService接口

3.创建UserService接口实现类

  • 同11.3.3UserServiceImpl实现类

4.applicationContext3.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 -->
    <!--切面:其实就是被模块化的特殊对象(实际上就是一个类)-->
    <bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"/>
    <!-- 开启注解支持 JDK(默认 proxy-target-class="true") cglib(proxy-target-class="true") -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
</beans>

5.创建测试类

public class MyTest {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");
        // 注意:动态代理的是接口
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
    
}

6.测试结果

在这里插入图片描述

好了,今天的有关AOP面向切面编程的学习就到此结束啦,欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连,我们下期见,拜拜啦!


参考视频链接:https://www.bilibili.com/video/BV1WE411d7Dv(【狂神说Java】Spring5最新教程IDEA版通俗易懂)

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-17 11:52:07  更:2021-10-17 11:52:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:25:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码