Spring API 接口和自定义类来实现AOP(Spring学习笔记十)

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();

    }
}

 测试结果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】引用与指针

​​ &#x1f331;博客主页&#xff1a;青竹雾色间. &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ✨人生如寄&#xff0c;多忧何为 ✨ 目录标题 前言一.引用&#xff08;Reference&#xff09;二.指针&#xff08;Pointer&#xff09;三. 比较与总结 前…

随机生成Long全范围数

随机生成Long全范围数 前言实现思路主要代码分区随机生成过程案例&#xff1a;随机生成100个数 朴素的比较总结 前言 使用自带的Random.nextLong()函数生成Long型的长整数&#xff0c;范围比较小&#xff0c;如下图。100个随机数没看见10以内的数字。所以考虑实现随机化生成大…

新质生产力丨zData X 数据库一体机助力财政一体化平台全面升级

在数字化转型的大潮中&#xff0c;某财政局积极响应国家财政管理现代化的战略部署&#xff0c;启动了财政一体化平台升级改造工程。该项目旨在将财政局内部各部门及其各自独立的业务系统进行全面整合&#xff0c;构建起一个集约化的财政管理平台&#xff0c;力求通过技术创新推…

【剑指offr--C/C++】JZ31 栈的压入、弹出序列

一、题目 二、思路及代码 借助一个辅助栈来模拟入栈过程&#xff0c; ①在入栈之前先判断当前要入栈的元素是否与出栈数组当前元素相同&#xff0c; ② 如果不相同就入栈&#xff1b; ③如果相同就不用入栈了&#xff08;不入栈出栈&#xff09;&#xff0c;然后再依次取出栈的…

Redis中的复制功能(五)

心跳检测 概述 在命令传播阶段&#xff0c;从服务器默认会以每秒一次的频率&#xff0c;向主服务器发送命令: REPLCONF ACK < replication_offset >其中replication_offset是从服务器当前的复制偏移量。 发送REPLCONF ACK命令对于主从服务器有三个作用: 1.检测主从服…

python学习23:python中的列表(list)中的常用方法

列表(list)中的常用方法 1.列表中常用的方法主要有如下的方法&#xff1a; 2.代码演示主要常用的方法 查找某元素在列表内的下标索引&#xff1a;list.index(元素&#xff09; start_list [coco, xuanxuan, taotao] # 1.1 查找某元素在列表内的下标索引 index start_list…

Arcgis研究区图经纬度(南北)切换为英文字体(SN)

只在做英文论文研究区图的时候用&#xff0c;平常为了方便还是切换为中文

BigInteger 大整数 比较大小

一、以整数型礼品交易为例子 int userSend Integer.valueOf(id);int amount Integer.valueOf(amountStr);int userAccept Integer.valueOf(userIdAccept);GiftService giftService new GiftService();boolean carry1 giftService.isHavePropertyByUserIdByGiftId(userSend…

C++实现vector

目录 前言 1.成员变量 2.成员函数 2.1构造函数 2.2析构函数 2.3begin,end 2.4获取size和capacity 2.5函数重载【】 2.6扩容reserve 2.7resize 2.8insert 2.9删除 2.10尾插、尾删 3.0拷贝构造函数 3.1赋值运算符重载 前言 自主实现C中vector大部分的功能可以使我们更好的理解并使…

第二十二章 Maven

一、Maven 1. Maven 简介 Maven 是一个项目管理工具&#xff0c;可以对 Java 项目进行自动化的构建和依赖管理。Maven 在美国是一个口语化的词语&#xff0c;代表专家、内行的意思&#xff0c;约等于北京话中的老炮儿。有老炮儿在身边&#xff0c;项目经理可谓得心应手。 项…

Redis的5大常见数据类型的用法

上一篇文章我们讲了Redis的10大应用场景&#xff0c;这一篇文章就针对Redis的常用数据结构进行一个说明&#xff0c;通过示例的形式演示每一种数据结构如何使用。 当涉及Redis的数据操作时&#xff0c;不同数据类型对应的不同数据结构&#xff0c;如下就对5大常用的数据类型进行…

[每周一更]-第92期:Go项目中的限流算法

这周五在清明假期内&#xff0c;提前更新文章 很多业务会有限流的场景&#xff0c;比如活动秒杀、社区搜索查询、社区留言功能&#xff1b;保护自身系统和下游系统不被巨型流量冲垮等。 在计算机网络中&#xff0c;限流就是控制网络接口发送或接收请求的速率&#xff0c;它可防…

k8s 部署 canal 集群,RocketMQ 模式

k8s 部署 canal 集群&#xff0c;RocketMQ 模式 k8s 部署 canal 集群&#xff0c;RocketMQ 模式前提MySQLRocketMQ制作 canal-admin、canal-server 镜像 部署 zookeeper部署 canal-admin部署 canal-server测试 k8s 部署 canal 集群&#xff0c;RocketMQ 模式 前提 MySQL 开启…

idea2023.2.1 java项目-web项目创建-servlet类得创建

如何创建Java项目 1.1 方式1&#xff1a; 1.2 方式&#xff1a; 1.3 方式 如何创建web项目 方式 ----- 推荐 如何创建servlet类 复制6 中得代码 给servlet 配置一个路径 启动tomcat 成功了

Plonky2.5:在Plonky2中验证Plonky3 proof

1. 引言 Plonky2.5为QED Protocol团队主导的项目&#xff0c;定位为&#xff1a; 在Plonky2 SNARK中验证Plonky3 STARK proof。 从而实现Plonky系列的递归证明。 开源代码实现见&#xff1a; https://github.com/QEDProtocol/plonky2.5https://github.com/Plonky3/Plonky3&a…

go库x/text缺陷报告CVE-2022-32149的处理方案

#问题描述 go库 golang.org/x/text &#xff0c;注意这里不是go的源码&#xff0c; 在0.3.8版本之前存在一个缺陷(Vulnerability) 缺陷ID CVE-2022-32149 具体描述 攻击者可以通过制作一个Accept-Language报头来导致拒绝服务。 具体的原因是&#xff0c;在解析这个Accept-L…

Scala第十九章节(Actor的相关概述、Actor发送和接收消息以及WordCount案例)

Scala第十九章节 章节目标 了解Actor的相关概述掌握Actor发送和接收消息掌握WordCount案例 1. Actor介绍 Scala中的Actor并发编程模型可以用来开发比Java线程效率更高的并发程序。我们学习Scala Actor的目的主要是为后续学习Akka做准备。 1.1 Java并发编程的问题 在Java并…

如何通过ArkTS卡片的Canvas自定义绘制能力实现五子棋游戏卡片

介绍 本示例展示了如何通过ArkTS卡片的Canvas自定义绘制能力实现一个简单的五子棋游戏卡片。 使用Canvas绘制棋盘和黑白棋子的落子。通过卡片支持的点击事件进行交互&#xff0c;让用户在棋盘上进行黑白棋子的对局。通过TS的逻辑代码实现五子棋输赢判定、回退等逻辑计算&…

Linux制作C++静态库和动态库并使用示例

创建动态库&#xff1a; 编写源文件&#xff1a; // sub.h 显式调用 #include <iostream>extern "C" int sub(int a, int b);// sub.cpp #include "sub.h"int sub(int a, int b) {return a - b; }// quadrature.h 隐式调用 #include <iostream&…

dhcp中继代理

不同过路由器分配ip了&#xff0c;通过一台服务器来代替&#xff0c;路由器充当中继代理功能&#xff0c;如下图 服务器地址&#xff1a;172.10.1.1/24 配置流程&#xff1a; 1.使能dhcp功能 2.各个接口网关地址&#xff0c;配置dhcp中继功能 dhcp select relay &#xff0…