【SSM】Spring6(十.面向切面编程AOP)

news2024/10/4 15:24:26

文章目录

  • 1.AOP
  • 2. AOP的七大术语
  • 3. 切点表达式
  • 4.使用Spring的AOP
    • 4.1 环境准备
    • 4.2 基于AspectJ的AOP注解式开发步骤
    • 4.3 所有通知类型
    • 4.4 切面顺序
    • 4.5 通用切点
    • 4.6 获取目标方法的方法签名
    • 4.7 全注解式开发
    • 4.8 基于XML配置的AOP
  • 5. 案例:事务处理

1.AOP

将与核心业务无关的代码独立的抽取出来,形成一个独立的组件,然后以横向交叉的方式应用到业务流程当中的过程被称为AOP。

优点:
● 第一:代码复用性增强。
● 第二:代码易维护。
● 第三:使开发者更关注业务逻辑。

2. AOP的七大术语

public class UserService{
    public void do1(){
        System.out.println("do 1");
    }
    public void do2(){
        System.out.println("do 2");
    }
    public void do3(){
        System.out.println("do 3");
    }
    public void do4(){
        System.out.println("do 4");
    }
    public void do5(){
        System.out.println("do 5");
    }
    // 核心业务方法
    public void service(){
    try{
    	//Joinpoint连接点
        do1();  //Pointcut切点
        //Joinpoint连接点
        do2();   //Pointcut切点
        //Joinpoint连接点
        do3();   //Pointcut切点
        //Joinpoint连接点
        do5();   //Pointcut切点
          //Joinpoint连接点
    } catch (Exception e){
    	  //Joinpoint连接点
      }finallly{
      	  //Joinpoint连接点
      }
    }
}
  • 连接点 Joinpoint
    描述的是位置,程序执行过程中,可以织入切面的位置。方法的执行前后,异常抛出之后等位置
  • 切点 Pointcut
    真正织入切面的方法。
  • 通知 Advice
    又叫增强,就是要增强的那段具体的代码。
    包括
    ■ 前置通知
    ■ 后置通知
    ■ 环绕通知
    ■ 异常通知
    ■ 最终通知
  • 切面 Aspect
    切面 = 切点+通知
  • 织入 Weaving
    把通知应用到目标对象上的过程。
  • 代理对象Proxy
    一个目标对象被织入通知后产生的新对象。
  • 目标对象Target
    被织入通知的对象。

(注:连接点和切入点的区别)

举个例子,开车到高速路口有很多的出口(连接点),但是我们实际上只从一个出口出去(切入点)

3. 切点表达式

切点表达式用来定义通知(Advice)往哪些方法上切入。
语法:

execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])

访问控制权限修饰符:
● 可选项。
● 没写,就是4个权限都包括。
● 写public就表示只包括公开的方法。
返回值类型:
● 必填项。
* 表示返回值类型任意。
全限定类名:
● 可选项。
● 两个点“…”代表当前包以及子包下的所有类。
● 省略时表示所有的类。
方法名:
● 必填项。
*表示所有方法。
● set*表示所有的set方法。
形式参数列表:
● 必填项
● () 表示没有参数的方法
● (…) 参数类型和个数随意的方法
● (*) 只有一个参数的方法
● (*, String) 第一个参数类型随意,第二个参数是String的。
异常:
● 可选项。
● 省略时表示任意异常类型。

4.使用Spring的AOP

Spring对于AOP的实现主要有三种方式:
● 第一种方式:Spring框架结合AspectJ框架实现的AOP,基于注解方式。
● 第二种方式:Spring框架结合AspectJ框架实现的AOP,基于XML方式。
● 第三种方式:Spring框架自己实现的AOP,基于XML配置方式。

4.1 环境准备

依赖

<!--仓库-->
    <repositories>
        <repository>
            <id>repository.spring.milestone</id>
            <name>Spring Milestone Repository</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <!--依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

spring配置文件

<?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 http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>

4.2 基于AspectJ的AOP注解式开发步骤

目标类

package com.sdnu.spring6.service;

import org.springframework.stereotype.Service;

@Service("userService")
public class UserService {  //目标类
    public void login(){  //目标方法
        System.out.println("系统正在进行身份验证");
    }
}

切面

package com.sdnu.spring6.service;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component("logAspect")
@Aspect //切面类需要注解标注
public class LogAspect {  //切面 = 通知 + 切点
    @Before("execution(* com.sdnu.spring6.service.UserService.*(..))")
    public void myMethod(){
        System.out.println("一个通知--》增强代码");
    }
}

spring配置文件

<?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 http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--组件扫描-->
    <context:component-scan base-package="com.sdnu.spring6.service"/>
    <!--开启aspectj的动态代理-->
    <!--
    proxy-target-class="true"表示强制使用CGLIB动态代理
    proxy-target-class="false"默认的,表示接口使用JDK动态代理,反之使用CGLIB动态代理
    -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

测试

package com.sdnu.spring6.Test;

import com.sdnu.spring6.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringAopTest {
    @Test
    public void testBefore(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.login();
    }
}

在这里插入图片描述

4.3 所有通知类型

● 前置通知:@Before 目标方法执行之前的通知
● 后置通知:@AfterReturning 目标方法执行之后的通知
● 环绕通知:@Around 目标方法之前添加通知,同时目标方法执行之后添加通知。
● 异常通知:@AfterThrowing 发生异常之后执行的通知
● 最终通知:@After 放在finally语句块中的通知

4.2的例子是前置通知,后置通知也类似。

环绕通知:

    //环绕在前置通知之前,后置通知之后
    @Around("execution(* com.sdnu.spring6.service..*(..))")
    public void aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("前环绕");
        //执行目标代码
        joinPoint.proceed();
        System.out.println("后环绕");
    }

异常通知:

    @AfterThrowing("execution(* com.sdnu.spring6.service..*(..))")
    public void afterThrowingAdvice(){
        System.out.println("异常通知");
    }

最终通知:

 @After("execution(* com.sdnu.spring6.service..*(..))")
    public void afterAdvice(){
        System.out.println("最终通知");
    }

4.4 切面顺序

在这里插入图片描述
在这里插入图片描述
@Order(num) ,num越小,则优先级越高。

4.5 通用切点

在这里插入图片描述

    @Pointcut("execution(* com.sdnu.spring6.service..*(..))")
    public void universalPointcut(){

    }

4.6 获取目标方法的方法签名

    @Before("universalPointcut()")
    public void myMethod(JoinPoint joinPoint){
        System.out.println("一个通知--》增强代码");
        Signature signature = joinPoint.getSignature();//获取目标方法的方法签名
        System.out.println(signature.getName());
    }

4.7 全注解式开发

Spring6Config

package com.sdnu.spring6.service;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration //代替spring配置文件
@ComponentScan({"com.sdnu.spring6.service"}) //组件扫描
@EnableAspectJAutoProxy(proxyTargetClass = true) //启用aspect的自动代理机制
public class Spring6Config {
}

测试

    @Test
    public void testNoXml(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Spring6Config.class);
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.logout();
    }

4.8 基于XML配置的AOP

 <!--纳入spring bean管理-->
    <bean id="vipService" class="com.sdnu.spring6.service.VipService"/>
    <bean id="timerAspect" class="com.sdnu.spring6.service.TimerAspect"/>

    <!--aop配置-->
    <aop:config>
        <!--切点表达式-->
        <aop:pointcut id="p" expression="execution(* com.sdnu.spring6.service.VipService.*(..))"/>
        <!--切面-->
        <aop:aspect ref="timerAspect">
            <!--切面=通知 + 切点-->
            <aop:around method="time" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>

5. 案例:事务处理

账户类

package com.sdnu.spring6.service;

import org.springframework.stereotype.Service;

@Service
public class AccountService {
    public void transfer(){
        System.out.println("正在转账");
    }
    public void withdraw(){
        System.out.println("正在取钱");
    }
}

订单类

package com.sdnu.spring6.service;

import org.springframework.stereotype.Service;

@Service
public class OrderService {
    public void generate(){
        System.out.println("正在生成订单");
    }
    public void cancel(){
        System.out.println("订单已经取消");
    }
}

切面

package com.sdnu.spring6.service;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class TransactionAspect {
    @Around("execution(* com.sdnu.spring6.service..*(..))")
    public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        try {
            //前环绕
            System.out.println("开启事务");
            //执行目标
            proceedingJoinPoint.proceed();
            //后环绕
            System.out.println("关闭事务");
        } catch (Throwable e) {
            System.out.println("回滚事务");
            e.printStackTrace();
        }
    }
}

spring配置文件

<?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 http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--组件扫描-->
    <context:component-scan base-package="com.sdnu.spring6.service"/>
    <!--启动自动代理-->
    <aop:aspectj-autoproxy/>
</beans>

测试

package com.sdnu.spring.spring6.test;

import com.sdnu.spring6.service.AccountService;
import com.sdnu.spring6.service.OrderService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopRealAppTest {
    @Test
    public void testTransaction(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
        OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
        accountService.transfer();
        accountService.withdraw();
        orderService.generate();
        orderService.cancel();
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/421800.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Visual Studio Code跳转到CSS定义

Visual Studio Code 快速跳转到 VUE文件 或 CSS文件的定义位置&#xff08;跳转到class定义&#xff0c;跳转到css定义&#xff09;&#xff0c;插件Css Peek、Vue Peek 对提升开发效率上&#xff0c;事半功倍。 目录 1、跳转到CSS定义 1.1、CSS Peek 1.2、Vue Peek 2、其他…

舌体胖瘦的自动分析-曲线拟合-或许是最简单判断舌形的方案(六)

返回至系列文章导航博客 1 简介 在中医智能舌诊项目中需要舌体胖瘦的自动分析 舌体胖瘦是中医诊断中重要的观察依据&#xff0c;。胖大舌“舌色淡白&#xff0c;舌体胖嫩&#xff0c;比正常舌大而厚&#xff0c;甚至充满口腔”&#xff0c;主脾肾阳虚&#xff0c;气化失常&am…

C++无符号整型与有符号整型变量的运算-不简单

示例分析&#xff1a; #include<iostream> #include <stdio.h>struct Result {char c;char d;unsigned char e; };Result getChar(int x, int y) {Result res;unsigned int a x;(a y > 10) ? (res.c 1) : (res.c 2);res.d a y;res.e a y;return res; …

RHCE第一次作业at和cront两个任务管理程序的区别

1.at 单一执行的例行性工作&#xff1a;仅处理执行一次就结束了 -m 当任务完成之后&#xff0c;即使没有标准输出&#xff0c;将给用户发送邮件 -l atq的别名&#xff0c;可列出目前系统上面的所有该用户的at调度 -d atrm的别名,可以取消一个在at调度中的工作 -v 使用较明显的…

基于html+css的图片展示11

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

信息安全保障人员CISAW认证基础级、专业级通用认证条件

信息安全保障人员认证&#xff08;Certified Information Security Assurance Worker&#xff0c;简称“CISAW”&#xff09;是中国网络安全审查技术与认证中心针对信息安全保障领域不同专业技术方向、应用方向和保障岗位&#xff0c;依据国际标准ISO/IEC 17024《人员认证机构通…

HTTPS-TSL握手

HTTP一般基于TCP协议&#xff0c;而HTTPS就是在这之间加了SSL/TLS协议&#xff0c;那么在TCP三次握手建立TCP连接后&#xff0c;就需要TLS握手建立SSL/TLS连接。 TLS握手-流程 &#xff08;基于RSA算法&#xff09; &#xff08;1&#xff09;首先&#xff0c;客户端向服务器发…

Unity快手上手【熟悉unity编辑器,C#脚本控制组件一些属性之类的】

Unity学习参考文档和开发工具 ☺ unity的官网文档&#xff1a;https://docs.unity3d.com/cn/current/Manual/ScriptingSection.html ■ 学习方式&#xff1a; 首先了解unity相关概述&#xff0c;快速认识unity编辑器&#xff0c;然后抓住重点的学&#xff1a;游戏对象、组件|…

【C++】1. 命名空间

文章目录一、命名空间的由来二、命名空间的使用2.1 关键字&#xff1a;namespace2.2 访问命名空间里的标识符2.3 命名空间的特点三、总结一、命名空间的由来 当我们使用c语言编写项目时&#xff0c;可能遇到以下情况&#xff1a; 变量名与某个库函数名重复&#xff0c;导致保…

sscanf和snprintf格式化时间字符串的日期与时间戳相互转换用法

sscanf格式化时间字符串的用法 UTC&#xff1a;Coordinated Universal Time 协调世界时。因为地球自转越来越慢&#xff0c;每年都会比前一年多出零点几秒&#xff0c;每隔几年协调世界时组织都会给世界时1秒&#xff0c;让基于原子钟的世界时和基于天文学&#xff08;人类感知…

测试技术与信号处理实验报告

目录 金属箔式应变片——单臂电桥性能实验 金属箔式应变片——半桥性能实验 金属箔式应变片——全桥性能实验 差动变压器的性能实验 直流全桥的应用——电子秤实验 交流激励时霍尔式传感器的位移特性实验 电容式传感器的位移实验 磁电式转速传感器测速实验 金属箔式应变…

C++ -- 继承

文章目录1. 继承的概念和定义1.1 概念1.2 定义1.2.1 定义格式1.2.2 继承基类成员访问方式的变化2. 基类和派生类对象赋值转换3. 继承中的作用域4. 派生类的默认成员函数5. 继承与友元6. 继承与静态成员7. 复杂的菱形继承及菱形虚拟继承8. 继承和组合1. 继承的概念和定义 1.1 概…

听歌无线耳机哪个品牌好?2023适合听歌的好音质蓝牙耳机推荐

现如今&#xff0c;不管是听歌、追剧或是玩游戏&#xff0c;不少人喜欢戴蓝牙耳机进行。因为蓝牙耳机的功能更丰富&#xff0c;连接方便&#xff0c;还摆脱了线的束缚&#xff0c;使用起来更方便。那么&#xff0c;听歌无线耳机哪个品牌好&#xff1f;针对这个问题&#xff0c;…

『造轮子』亿级短URL生成器的架构设计及源码分享

&#x1f4e3;读完这篇文章里你能收获到 了解博主的短链生成的架构设计思路学习不同的短链技术方案选择学习基于混淆的自增短URL算法了解博主造的轮子SuperShortLink短链开源项目感谢点赞收藏&#xff0c;避免下次找不到~ 文章目录一、需求分析1. 短链生成及访问需求2. 短链应…

Python+requests+unittest+excel接口自动化测试框架

一、框架结构&#xff1a; 工程目录 二、Case文件设计 三、基础包 base 3.1 封装get/post请求&#xff08;runmethon.py&#xff09; 1 import requests2 import json3 class RunMethod:4 def post_main(self,url,data,headerNone):5 res None6 if heade…

互联网医院源码|搭建互联网医院系统时运营需要哪些资质?

目前一线城市已经都有完善的医疗系统&#xff0c;人们对于线上问诊系统越来越熟悉&#xff0c;使用的人也越来越多&#xff0c;对于一些偏远的地区来说在线问诊平台有着更广泛的应用和意义&#xff0c;互联网医院开发实现了医疗资源共享的情况&#xff0c;打破了地域限制&#…

文献管理软件Endnote、Mendeley、Zotero比较及选择,Zotero基础使用技巧

引言 大家好&#xff0c;我是比特桃。日常开发的项目分为两种&#xff0c;一种是成熟化的工程项目&#xff0c;只需要与具体的业务紧密结合及应用&#xff0c;难点也比较偏向于软件工程或者互联网高并发的方向。这种项目我们通常不会选择去查文献去寻找问题的解决办法&#xf…

微信小程序开发 | 音乐小程序项目

音乐小程序项目3.1 开发前的准备3.1.1 项目展示3.1.2 项目分析3.1.3 项目初始化3.2 【任务1】标签页切换3.2.1 任务分析3.2.2 前导知识3.2.3 编写页面结构和样式3.2.4 实现标签页切换3.3 【任务2】音乐推荐3.3.1 任务分析3.3.2 前导知识3.3.3 内容区域滚动3.3.4 轮播图3.3.5 功…

15-721 chapter2 内存数据库

Background 随着时代的发展&#xff0c;DRAM可以容纳足够的便宜&#xff0c;容量也变大了。对于数据库来说&#xff0c;数据完全可以fit in memory&#xff0c;但同时面向disk的数据库架构不能很好的发挥这个特性 这张图是disk database的cpu instruction cost 想buffer pool…

使用PyG(PyTorch Geometric)实现基于图卷积神经网络(GCN)的节点分类任务

文章目录基本介绍PyTorch Geometric图卷积神经网络GCN节点分类任务实现Cora数据集搭建GCN模型训练与测试迭代并输出完整代码基本介绍 PyTorch Geometric PyG&#xff08;PyTorch Geometric&#xff09;是一个基于PyTorch的库&#xff0c;可以轻松编写和训练图神经网络&#x…