初学Spring之 AOP 面向切面编程

news2024/10/6 12:25:14

AOP(Aspect Oriented Programming)面向切面编程

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

是面向对象(OOP)的延续

AOP 在 Spring 中的作用:

1.提供声明式事务

2.允许用户自定义切面

导入 jar 包,搜索 AspectJ Weaver

(复制过来把 <scope>runtime</scope> 这行删去,不然注解报错)

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.22.1</version>
    </dependency>

方法一:使用原生 Spring API 接口实现

先写个 UserService 接口:

package com.demo.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

再写个 UserServiceImpl 类来实现接口,重写方法

package com.demo.service;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增");
    }

    @Override
    public void delete() {
        System.out.println("删");
    }

    @Override
    public void update() {
        System.out.println("改");
    }

    @Override
    public void select() {
        System.out.println("查");
    }
}

写个 Log 类来实现 MethodBeforeAdvice 接口(前置日志)

method:要执行的目标对象的方法

args:参数

target:目标对象

package com.demo.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {

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

再写个 AfterLog 类来实现 AfterReturningAdvice 接口(后置日志)

returnValue 返回值

package com.demo.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {

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

配置 applicationContext.xml 文件

注册 bean

配置 aop:需要导入 aop 的约束

xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd

使用原生 Spring API 接口

<aop:config>

 切入点:expression:表达式,execution(要执行的位置:修饰词 返回值 类名 方法名 参数)

<aop:pointcut id="xx" expression="execution(* com.demo.service.UserServiceImpl.*(..))"/>

执行环绕增加

<aop:advisor advice-ref="xx" pointcut-ref="xx"/>

<?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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       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
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
						http://www.springframework.org/schema/util
						http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- 注册bean -->
    <bean id="user" class="com.demo.service.UserServiceImpl"/>
    <bean id="log" class="com.demo.log.Log"/>
    <bean id="afterLog" class="com.demo.log.AfterLog"/>

    <!-- 使用原生Spring API接口 -->
    <!-- 配置aop:需要导入aop的约束 -->
    <aop:config>
        <!-- 切入点:expression:表达式,execution(要执行的位置:修饰词 返回值 类名 方法名 参数) -->
        <aop:pointcut id="pointcut" expression="execution(* com.demo.service.UserServiceImpl.*(..))"/>

        <!-- 执行环绕增加 -->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

写个测试类

动态代理,代理的是接口

import com.demo.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

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

执行结果如下:

方法二:自定义类来实现 AOP(切面定义)

增加一个自定义的类

package com.demo.pointcut;

public class PointCut {
    public void before(){
        System.out.println("方法执行前");
    }

    public void after(){
        System.out.println("方法执行后");
    }
}
<?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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       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
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
						http://www.springframework.org/schema/util
						http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- 注册bean -->
    <bean id="user" class="com.demo.service.UserServiceImpl"/>
    <bean id="log" class="com.demo.log.Log"/>
    <bean id="afterLog" class="com.demo.log.AfterLog"/>

    <!-- 自定义类 -->
    <bean id="diy" class="com.demo.pointcut.PointCut"/>

    <aop:config>
        <!-- 自定义切面,ref:要引用的类 -->
        <aop:aspect ref="diy">
            <!-- 切入点 -->
            <aop:pointcut id="pointcut" expression="execution(* com.demo.service.UserServiceImpl.*(..))"/>
            <!-- 通知 -->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

</beans>

 自定义切面,ref:要引用的类

<aop:aspect ref="xx">

切入点:

<aop:pointcut id="pointcut" expression="execution(* com.demo.service.UserServiceImpl.*(..))"/>

通知:

<aop:before method="xx" pointcut-ref="xx"/>

测试类不变,执行结果如下:

方法三:使用注解实现 AOP

注意导入包不要导错

package com.demo.pointcut;

//使用注解方式实现AOP
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect //标注这个类是一个切面
public class AnnotationPointCut {

    @Before("execution(* com.demo.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }

    @After("execution(* com.demo.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("方法执行后");
    }

    //在环绕增强中,可以给定一个参数,代表要获取处理切入的点
    @Around("execution(* com.demo.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前");

        Signature signature = joinPoint.getSignature(); //获得签名
        System.out.println(signature);

        //执行方法
        Object proceed = joinPoint.proceed();

        System.out.println("环绕后");

        System.out.println(proceed);
    }
}

开启注解支持:<aop:aspectj-autoproxy/>

<?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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       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
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
						http://www.springframework.org/schema/util
						http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- 注册bean -->
    <bean id="user" class="com.demo.service.UserServiceImpl"/>
    <bean id="log" class="com.demo.log.Log"/>
    <bean id="afterLog" class="com.demo.log.AfterLog"/>

    <bean id="anno" class="com.demo.pointcut.AnnotationPointCut"/>
    <!-- 开启注解支持 -->
    <aop:aspectj-autoproxy/>
    
</beans>

测试类不变,执行结果如下:

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

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

相关文章

ISO 50001:企业节能减排与可持续发展的双赢之道

在全球气候变化日益严峻、资源日益稀缺的今天&#xff0c;能源管理已成为企业可持续发展不可或缺的一部分。ISO 50001作为国际能源管理体系标准&#xff0c;正在全球范围内被越来越多的企业采纳。它不仅帮助企业提高能源效率&#xff0c;减少能源消耗&#xff0c;还在多个方面对…

Java的基础语法

叠甲&#xff1a;以下文章主要是依靠我的实际编码学习中总结出来的经验之谈&#xff0c;求逻辑自洽&#xff0c;不能百分百保证正确&#xff0c;有错误、未定义、不合适的内容请尽情指出&#xff01; 文章目录 1.第一份程序1.1.代码编写1.2.代码运行1.2.1.命令行编译1.2.2.IEDA…

存储结构与管理磁盘

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、一切从“/”开始 二、物理设备的命名规则 三、文件系统与数据资料 四、挂载硬件设备 五、添加硬盘设备 六、添加交换分区 七、磁盘容…

Linux系统的介绍和常用命令

文章目录 介绍常用命令文件和目录操作文件内容操作系统管理命令网络命令 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;Liunx系统 ✨文章内容&#xff1a;Liunx系统介绍 &…

C语言 | Leetcode C语言题解之第217题存在重复元素

题目&#xff1a; 题解&#xff1a; struct hashTable {int key;UT_hash_handle hh; };bool containsDuplicate(int* nums, int numsSize) {struct hashTable* set NULL;for (int i 0; i < numsSize; i) {struct hashTable* tmp;HASH_FIND_INT(set, nums i, tmp);if (tm…

css导航栏遮挡住垂直滚动条,以及100vw引起的横向滚动条出现

滚动条被导航栏遮住问题 解决前 解决过程 一开始想要body的宽度为整个视口的宽度 100vw view width 不过出现了横向滚动条 于是乎想着给所有元素增加 x轴溢出时隐藏 问题解决&#xff0c;不过顶部的导航栏由于设置了fixed 又把右边导航栏挡住了 可能因为 body 占100视口宽度…

简单且循序渐进地查找软件中Bug的实用方法

“Bug”这个词常常让许多开发者感到头疼。即使是经验丰富、技术娴熟的开发人员在开发过程中也难以避免遭遇到 Bug。 软件中的故障会让程序员感到挫败。我相信在你的软件开发生涯中&#xff0c;也曾遇到过一些难以排查的问题。软件中的错误可能会导致项目无法按时交付。因此&…

【python】python当当数据分析可视化聚类支持向量机预测(源码+数据集+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【C++】map和set详解

目录 1. 关联式容器 2. 键值对pair 3. 树形结构的关联式容器 4. set 4.1 set的介绍 4.2 set的构造 4.3 set的迭代器 4.4 set的容量 4.5 set的常用函数 5. multiset 6. map 6.1 map的介绍 6.2 map的构造 6.3 map的迭代器 6.4 map的容量 6.5 map的operator[] 6.6…

【学习笔记】程序设计竞赛

程序设计竞赛 文章目录 程序设计竞赛0x00 基本操作指南0x01 算法分析0x02 STL和基本数据结构栈队列集合map 0x03 排序插入排序归并排序&#xff08;Merge Sort)快速排序 0x04 搜索技术BFSDFS回溯与剪枝 深度迭代ID A*A star双向广搜 0x05 递推方程0x06 高级数据结构并查集二叉树…

STM32快速复习(八)SPI通信

文章目录 前言一、SPI是什么&#xff1f;SPI的硬件电路&#xff1f;SPI发送的时序&#xff1f;二、库函数二、库函数示例代码总结 前言 SPI和IIC通信算是我在大学和面试中用的最多&#xff0c;问的最多的通信协议 IIC问到了&#xff0c;一般SPI也一定会问到。 SPI相对于IIC多了…

HTTP请求响应/与HTTPS区别

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;和HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是用于在计算机网络上传输信息的两种协议。 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;: HTTP 是一种用于传输超文本的应用层协议…

Go 依赖注入设计模式

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

前后端分离系统

前后端分离是一种现代软件架构模式&#xff0c;特别适用于Web应用开发&#xff0c;它强调将用户界面&#xff08;前端&#xff09;与服务器端应用逻辑&#xff08;后端&#xff09;相分离。两者通过API接口进行数据交互。这种架构模式的主要优势在于提高开发效率、维护性和可扩…

安卓虚拟位置修改

随着安卓系统的不断更新&#xff0c;确保软件和应用与最新系统版本的兼容性变得日益重要。本文档旨在指导用户如何在安卓14/15系统上使用特定的功能。 2. 系统兼容性更新 2.1 支持安卓14/15&#xff1a;更新了对安卓14/15版本的支持&#xff0c;确保了软件的兼容性。 2.2 路…

《算法笔记》总结No.3——排序

基础算法之一&#xff0c;相当重要。在普通的机试中如果没有数据类型和时空限制&#xff0c;基本上选择自己最熟悉的就好。本篇只总结选择排序和插入排序&#xff0c;侧重应用&#xff0c;408中要求的种类更加繁多&#xff0c;此处先不扩展难度~总结最常用的两种排序。 一.选择…

HTML 【实用教程】(2024最新版)

核心思想 —— 语义化 【面试题】如何理解 HTML 语义化 ?仅通过标签便能判断内容的类型&#xff0c;特别是区分标题、段落、图片和表格 增加代码可读性&#xff0c;让人更容易读懂对SEO更加友好&#xff0c;让搜索引擎更容易读懂 html 文件的基本结构 html 文件的文件后缀为 …

VMware虚拟机配置桥接网络

转载&#xff1a;虚拟机桥接网络配置 一、VMware三种网络连接方式 VMware提供了三种网络连接方式&#xff0c;VMnet0, VMnet1, Vmnet8&#xff0c;分别代表桥接&#xff0c;Host-only及NAT模式。在VMware的编辑-虚拟网络编辑器可看到对应三种连接方式的设置&#xff08;如下图…

深度解析Ubuntu版本升级:LTS版本升级指南

深度解析Ubuntu版本升级&#xff1a;Ubuntu版本生命周期及LTS版本升级指南 Ubuntu是全球最受欢迎的Linux发行版之一&#xff0c;其版本升级与维护策略直接影响了无数用户的开发和生产环境。Canonical公司为Ubuntu制定了明确的生命周期和发布节奏&#xff0c;使得社区、企业和开…

viscode-插件

vue组件生成&#xff1a; vue.json {"Print to console": {"prefix": "vue", "body": ["<!-- $1 -->","<template>","<div>","</div>","</template>&q…