AOP的实现方式一(Spring学习笔记十)

news2024/11/27 14:52:03

1、什么是AOP

全称是 Aspect Oriented Programming 即:面向切面编程。是OOP(面向对象编程)的延续,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。简单的说他就是把我们程序重复的代码抽取出来,在需要执行的时候使用动态代理技术在不修改源码的基础上,对我们的已有方法进行增强。

AOC在Spring中的作用

2、使用Spring实现AOP

方式一:使用Spring的API接口来做

1、导入AOP支持
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
    <scope>runtime</scope>
</dependency>
2、创建测试类

抽象类:

package com.li.service;

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

抽象类实现:

package com.li.service;

public class UserServiceImp 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("查询");
    }
}
 3、创建切面类,编写切面方法

方法一:实现MethodBeforeAdvice  在切入点之前切入方法

package com.li.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    //实现MethodBeforeAdvice会在方法执行前运行
    //method: 要执行的目标对象的方法
    //args:参数
    //target:目标对象
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了,"+"参数是:"+args.getClass().getName());
    }
}

方法二:实现 AfterReturningAdvice  在切入点后加入切面方法

package com.li.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    //实现AfterReturningAdvice会在方法执行后执行
    //method: 要执行的目标对象的方法
    //args:参数
    //target:目标对象
    //返回值:returnValue
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"执行了:"+method.getName()+"方法,方法参数是:"+args.getClass().toString()+"返回值是:"+returnValue);
    }
}
4、创建配置文件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
		https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
		https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注册Bean-->
    <bean id="UserService" class="com.li.service.UserServiceImp"/>
    <bean id="log" class="com.li.log.Log"/>
    <bean id="AfterLog" class="com.li.log.AfterLog"/>

    <!--使用原生Spring api接口-->
    <!--配置aop: 需要先导入aop的约束 xmlns:aop="http://www.springframework.org/schema/aop"    http://www.springframework.org/schema/aop
		https://www.springframework.org/schema/aop/spring-aop.xsd"-->
    <aop:config>
    <!--需要一个切入点就是我们需要在什么地方去执行我们的Spring的方法-->
    <!--id后面接你想给切入点取的名字 expression需要接表达式,表达式是死的:execution(* 要执行的位置.*(..))    这里的.*表示位置下的所有方法 (..)表示可以有任意的参数-->
        <aop:pointcut id="poi" expression="execution(* com.li.service.UserServiceImp.*(..))"/>

    <!--执行环绕增强-->
        <aop:advisor advice-ref="log" pointcut-ref="poi"/>
        <aop:advisor advice-ref="AfterLog" pointcut-ref="poi"/>
    </aop:config>
</beans>
5、测试类测试
package com.li.log;

import com.li.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestGo {
    @Test
    public void test1(){
        //通过配置文件获取ClassPath
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //根据抽象类获取Bean
        UserService user = context.getBean("UserService", UserService.class);
        //调用方法测试
        user.add();

    }
}

 测试结果

方式二:使用自定义类来实现Aop

创建自定义类和方法

package com.li.diy;

public class Diy {
    public void before(){
        System.out.println("====切面之前执行====");
    }

    public void after(){
        System.out.println("====切面之后执行====");
    }
}

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

    <!--注册Bean-->
    <bean id="UserService" class="com.li.service.UserServiceImp"/>

    <!--方式二: 通过自定义方法来Aop-->
    <!--注册Bean-->
    <bean id="diy" class="com.li.diy.Diy"/>

    <!--配置aop: 需要先导入aop的约束 xmlns:aop="http://www.springframework.org/schema/aop"    http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd"-->
    <aop:config>

    <!--自定义切面,ref:接需要引用类的bean id-->
        <aop:aspect ref="diy">

            <!--id后面接你想给切入点取的名字 expression需要接表达式,表达式是死的:execution(* 要执行的位置.*(..))    这里的.*表示位置下的所有方法 (..)表示可以有任意的参数-->
            <aop:pointcut id="point" expression="execution(* com.li.service.UserServiceImp.*(..))"/>

            <!--通知 method后接前面类中自定义的方法名 pointcut-ref后接切入点的id -->
            <aop:before method="before" pointcut-ref="point"/>

            <aop:after method="after" pointcut-ref="point"/>


        </aop:aspect>

    </aop:config>
</beans>

创建测试类

package com.li.log;

import com.li.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestGo {
    @Test
    public void test1(){
        //通过配置文件获取ClassPath
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //根据抽象类获取Bean
        UserService user = context.getBean("UserService", UserService.class);
        //调用方法测试
        user.add();

    }
}

 测试结果

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

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

相关文章

【网站项目】泉文化管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

面试题:JVM的垃圾回收

一、GC概念 为了让程序员更专注于代码的实现&#xff0c;而不用过多的考虑内存释放的问题&#xff0c;所以&#xff0c;在Java语言中&#xff0c;有了自动的垃圾回收机制&#xff0c;也就是我们熟悉的GC(Garbage Collection)。 有了垃圾回收机制后&#xff0c;程序员只需要关…

java调用c++,使用clion进行JNI开发,ddl包生成以及so包生成

java调用c&#xff0c;使用clion进行JNI开发&#xff0c;ddl包生成以及so包生成 java基础代码生成C头部文件使用clion写C实现代码cmke打包构建使用java调用C执行linux环境下产生CPP的so包 java基础代码 先写好对应的基础代码&#xff0c;先不管static加载的ddl文件&#xff0c…

【JavaScript】数组 ③ ( JavaScript 数组长度 | 修改数组长度 | 数组案例 )

文章目录 一、JavaScript 数组长度1、数组长度2、修改数组长度 二、数组案例1、求数组元素平均值2、求数组元素最大值 一、JavaScript 数组长度 1、数组长度 在 JavaScript 中 , 数组长度 可以通过 数组变量的 length 属性 获取 , 该属性 返回 数组中的元素数量 , 也就是 数组长…

软件速成书:一夜成神的传说,还是现实的泡影?

嗨&#xff0c;各位小伙伴&#xff01; &#x1f431;‍&#x1f4bb; 我是【行走的程序喵】&#xff01;一个兼具Web前端和Java后端技能的技术宅&#xff01; &#x1f31f; 我的博客上分享最新的Web前端和Java后端技术文章&#xff0c;从基础入门到进阶应用&#xff0c;应有…

Linux系统----------探索mysql数据库MHA高可用

目录 一、MHA概述 1.1 什么是 MHA 1.2MHA 的组成 1.2.1MHA Node&#xff08;数据节点&#xff09; 1.2.2MHA Manager&#xff08;管理节点&#xff09; 1.3MHA 的特点 1.4MHA工作原理 1.5数据同步的方式 1.5.1同步复制 1.5.2异步复制 1.5.3半同步复制 二、搭建 MySQ…

夜神模拟器录制脚本录制键盘操作方法

很多用户们在使用夜神模拟器的时候&#xff0c;有个操作助手的功能非常的好用&#xff0c;用户们在录制自己的操作以后&#xff0c;就能够进行全自动的操作等&#xff0c;使用起来还是非常方便的&#xff0c;想要知道的用户们快来查看详细的教程吧~ 夜神模拟器录制脚本怎样录制…

5-规范设计(下):commit信息风格迥异、难以阅读,如何规范?

我们在做代码开发时&#xff0c;经常需要提交代码&#xff0c;提交代码时需要填写 Commit Message&#xff08;提交说明&#xff09;&#xff0c;否则就不允许提交。 所以在 Go 项目开发时&#xff0c;一个好的 Commit Message 至关重要&#xff1a; 可以使自己或者其他开发人…

3.26学习总结java初步实现学生管理系统

(该项目通过视频讲解过程中完成,其中将一些操作进行了修改和完善,其目的是为了巩固前面学习java的一些用法,熟悉写项目的过程) 一.项目要求 学生类: 属性:id、姓名、年龄、家庭住址 添加功能: 键盘录入每一个学生信息并添加&#xff0c;需要满足以下要求: ID唯一 删除功能…

Qt源码调试步骤记录

1.源码&#xff1a; 两种方式&#xff0c;要么安装qt时选择source&#xff0c;要么从官网下载源码&#xff0c;然后在qt creator中设置路径。二选一即可。我选的第二种。 1.1.第一种&#xff0c;安装时选择source&#xff1a; 1.2.第二种&#xff0c;下载源码设置路径&#x…

Linux中安装JDK17.X

1、总体概述&#xff1f; 该操作方式适合centos或red hat环境 2.1、在线下载JDK安装包&#xff1f; 通过wget命令下载JDK17.X包 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 如果提示&#xff1a;没有wget命令就安装wget yum install w…

Qt 富文本处理 (字体颜色大小加粗等)

Qt中支持HTML的控件有textEdit 、label 、textBrowser 。 接口&#xff1a;setHtml("Qt"); toHtml(). 文本样式设置 : 可分字设置 &#xff0c;主要使用QTextCharFormat类进行文本样式设置。 示例&#xff1a; QTextCharFormat fmt; //粗体 fmt.setFontWeight…

wps没保存关闭了恢复数据教程

有时候我们因为电脑问题会忘记保存就关闭wps导致数据丢失&#xff0c;不知道wps没保存关闭了怎么恢复数据&#xff0c;其实数据是无法恢复的。 wps没保存关闭了怎么恢复数据 1、wps没有数据恢复功能&#xff0c;不过可以开启自动备份。 2、我们可以先点击wps左上角的“文件”…

Vtk裁剪功能之平面裁剪vtkClipClosedSurface(vtk小记)

1.原理分析 对你的三维图形&#xff0c;使用一个平面切下去&#xff0c;然后保留一半。 确定一个平面&#xff1a;使用法向量和一个三维坐标点可以确定一个平面 原始图像 切一刀 切两刀&#xff0c;又一半 切三刀&#xff0c;又一半 源代码 #include <vtkActor.h> #i…

Linux 学习之路 -- 工具篇 -- gcc / g++

在 Linux 系统中&#xff0c;gcc 和 g 是两个常用的编译工具&#xff0c;分别用于编译 C 和 C 代码。下面我将介绍gcc、g的一些基本用法 目录 一、简单的认识 二、简单了解一下编译的过程 <1> 预处理阶段 <2>编译 <3>汇编 <4>链接…

SQLite数据库成为内存中数据库(三)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite使用的临时文件&#xff08;二&#xff09; 下一篇&#xff1a;SQLite中的原子提交&#xff08;四) ​​ SQLite数据库通常存储在单个普通磁盘中文件。但是&#xff0c;在某些情况下&#xff0c;数据库可能…

python爬虫基础------函数

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

打工人神器! Raccoon 代码小浣熊

继这三个之后&#xff0c;今天又来了一个 [ Raccoon代码小浣熊 ] 核心精要与产品特点 全面支持多种编程语言和IDE&#xff1a;「代码小浣熊」支持超过90种主流编程语言&#xff0c;包括但不限于Python、Java、JavaScript、C、Go和SQL等。同时&#xff0c;它集成了市面上主流的…

电脑换屏总结——关于我把电脑砸了这件事!

大家好&#xff0c;我是工程师看海&#xff0c;很高兴和各位一起分享我的原创文章&#xff0c;喜欢和支持我的工程师&#xff0c;一定记得给我点赞、收藏、分享哟。 加微信[chunhou0820]与作者进群沟通交流。 【淘宝】https://m.tb.cn/h.5PAjLi7?tkvmMLW43KO7q CZ3457 「运放秘…

【ENSP】交换机和交换机之间实现静态路由

1.概念 三层交换机只能在Vlanif逻辑口配置iP地址 2.实现方法 交换机允许对应vlan通行&#xff0c;配置vlanif的ip地址&#xff0c;做静态路由 3.静态路由配置方法 ip route-static 目的网段 子网掩码 下一跳设备 LSW1三层交换机配置 u t m sys vlan batch 10 20 …