Spring aop之针对注解
前言
接触过Spring的都知道,aop是其中重要的特性之一。笔者在开发做项目中,aop更多地是要和注解搭配:在某些方法上加上自定义注解,然后要对这些方法进行增强(很少用execution指定,哪些包下的哪些方法要增强)。那这时就要引出@annotation、@target、@within了。我们一一讲解。
@annotation
方法上是否有指定注解;子类调用不重写的方法会被aop拦截,调用重写的方法看是否加了指定注解。
首先引入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.7.4</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.7.4</version><scope>test</scope>
</dependency>
自定义一个注解:
import java.lang.annotation.Target;
import java.lang.annotation.*;@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Outer {int limit() default 0;}
目标类:
import org.springframework.stereotype.Component;@Component
public class Target {@Outer(limit = 8)public void invoke() {System.out.println("执行Target的方法");}}
@Component
public class SonTarget extends Target {}
切面类:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;@Component
@Aspect
public class MyAspect {@Around("@annotation(com.gs.spring_boot_demo.aop.Outer)")public Object around(ProceedingJoinPoint point) throws Throwable {Method method = ((MethodSignature)point.getSignature()).getMethod();Outer outer = method.getAnnotation(Outer.class);System.out.println("aop前置:" + outer.limit());return point.proceed();}}
编写测试类:
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.jupiter.api.Test;@SpringBootTest
public class AopTest {@Resourceprivate Target target;@Autowiredprivate SonTarget sonTarget;@Testpublic void aop() {target.invoke();System.out.println("---");sonTarget.invoke();}}
运行aop方法,打印结果:
把子类SonTarget修改一下,
import org.springframework.stereotype.Component;@Component
public class SonTarget extends Target {public void invoke() {System.out.println("子类执行Target的方法");}}
再次运行测试类,这时子类的invoke()方法不会被拦截了:
当然,如果SonTarget的invoke()方法上加上@Outer,那就能被aop拦截了。
@target
调用方法的对象,所属的类上是否有指定注解;注解被@Inherited修饰,子类调用会生效;无@Inherited,看子类上有无该注解。
自定义注解不动,目标类修改为:
import org.springframework.stereotype.Component;@Component
@Outer(limit = 8)
public class Target {public void invoke() {System.out.println("执行Target的方法");}}
import org.springframework.stereotype.Component;@Component
public class SonTarget extends Target {public void invoke() {System.out.println("子类执行Target的方法");}}
切面类修改为:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;@Component
@Aspect
public class MyAspect {/*** 要注意一下,@target很硬霸:所有的bean都会被动态代理(不管类上有没有加自定* 义注解),所以要约束为:本项目下的包下* 不然测试用例运行时会报错:依赖中有些类是final的,被动态代理会报错*/@Around("@target(com.gs.spring_boot_demo.aop.Outer) && within(com.gs.spring_boot_demo..*)")public void around(ProceedingJoinPoint point) throws Throwable {Method method = ((MethodSignature)point.getSignature()).getMethod();Outer outer = method.getDeclaringClass().getAnnotation(Outer.class);System.out.println("aop前置:" + outer.limit());point.proceed();}}
测试类不动,运行:
SonTarget的invoke()没有被拦截,想要被拦截,就在SonTarget类上添加@Outer;或者自定义注解上增加@Inherited(表明父类加上该注解后,子类能够继承):
import java.lang.annotation.Target;
import java.lang.annotation.*;@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Outer {int limit() default 0;}
@within
方法所属的类上,是否有指定注解;注解没有被@Inherited修饰,子类调用不重写的方法会被拦截,调用重写的方法看子类上是否有注解;注解被@Inherited修饰,子类调用方法都会被拦截,不管是否重写
自定义注解改一下,就把修饰它的@Inherited去掉;
目标类:
import org.springframework.stereotype.Component;@Component
@Outer(limit = 8)
public class Target {public void invoke() {System.out.println("执行Target的方法");}}
import org.springframework.stereotype.Component;@Component
public class SonTarget extends Target {}
切面类修改为:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;@Component
@Aspect
public class MyAspect {@Around("@within(com.gs.spring_boot_demo.aop.Outer)")public void around(ProceedingJoinPoint point) throws Throwable {Method method = ((MethodSignature)point.getSignature()).getMethod();Outer outer = method.getDeclaringClass().getAnnotation(Outer.class);System.out.println("aop前置:" + outer.limit());point.proceed();}}
测试类不动,运行:
子类的方法能被拦截;我们把子类的方法重写一下:
import org.springframework.stereotype.Component;@Component
public class SonTarget extends Target {public void invoke() {System.out.println("子类执行Target的方法");}}
再次运行测试类,打印出结果:
子类的方法没有被拦截,想要被拦截,SonTarget类上加上@Outer。
我们再试一下自定义注解被@Inherited修饰的情况。@Outer注解加上@Inherited,然后Target不动,SonTarget也不动(重写了invoke()方法,类上也没有@Outer),运行测试类:
SonTaget改一下,不重写invoke()方法,运行测试类:
相关文章:

Spring aop之针对注解
前言 接触过Spring的都知道,aop是其中重要的特性之一。笔者在开发做项目中,aop更多地是要和注解搭配:在某些方法上加上自定义注解,然后要对这些方法进行增强(很少用execution指定,哪些包下的哪些方法要增强)。那这时就…...

【JavaScript速成之路】JavaScript数据类型转换
📃个人主页:「小杨」的csdn博客 🔥系列专栏:【JavaScript速成之路】 🐳希望大家多多支持🥰一起进步呀! 文章目录前言数据类型转换1,转换为字符串型1.1,利用“”拼接转换成…...
21-绑定自定义事件
绑定自定义事件 利用自定义事件获取子组件的值 父组件给子组件绑定一个自定义事件,实际上是绑定到了子组件的实例对象vc上: <!-- 自定义myEvent事件 --> <Student v-on:myEventgetStudentName/>在父组件中编写getStudentName的实现&#…...
【Mysql】触发器
【Mysql】触发器 文章目录【Mysql】触发器1. 触发器1.1 介绍1.2 语法1.2.1 创建触发器1.2.2 查看触发器1.2.3 删除触发器1.2.4 案例1. 触发器 1.1 介绍 触发器是与表有关的数据库对象,指在insert、update、delete之前(BEFORE)或之后(AFTER),触发并执行…...

CODESYS开发教程11-库管理器
今天继续我们的小白教程,老鸟就不要在这浪费时间了😊。 前面一期我们介绍了CODESYS的文件读写函数库SysFile。大家可能发现了,在CODESYS的开发中实际上是离不开各种库的使用,其中包括系统库、第三方库以及用户自己开发的库。实际…...

【UnityAR相关】Unity Vuforia扫图片成模型具体步骤
1 资产准备 导入要生成的fbx模型(带有材质), 你会发现导入fbx的材质丢失了: 选择Standard再Extract Materials导出材质到指定文件夹下(我放在Assets->Materials了 ok啦! 材质出现了, 模型…...
2023年全国最新保安员精选真题及答案2
百分百题库提供保安员考试试题、保安职业资格考试预测题、保安员考试真题、保安职业资格证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 21.一般来说,最经济的巡逻方式是()。 A:步巡 B:…...

keil5安装了pack包但是还是不能选择device
一开始,我以为是keil5无法安装 STM32 芯片包,打开device倒是可以看到stm公司的芯片包,但是没有我想要的stm32f1。 我按照网上的一些说法,找到了这个STM32F1 的pack芯片包,但是我双击安装的时候,它的安装位…...

秒杀系统设计
1.秒杀系统的特点 瞬时高并发 2.预防措施 2.1.流量限制 对于一个相同的用户,限制请求的频次对于一个相同的IP,限制请求的频次验证码,减缓用户请求的次数活动开启之前,按钮先置灰,防止无效的请求流入系统࿰…...
全面认识数据指标体系
什么是数据指标体系? 看了下百度百科,竟然没有数据指标这个词条,看来这个词大家平时还用的不多啊。那只有间接偷懒一下,分别查下指标和数据这两个词条的含义,在组合起来看看。 数据:数据是指对客观事件进…...

热榜首推!阿里内部都在用的Java后端面试笔记,主流技术全在里面了!备战2023Java面试,拿理想offer
纵观今年的技术招聘市场, Java依旧是当仁不让的霸主 !即便遭受 Go等新兴语言不断冲击,依旧岿然不动。究其原因:Java有着极其成熟的生态,这个不用我多说;Java在 运维、可观测性、可监 控性方面都有着非常优秀…...

Android架构设计——【 APT技术实现butterknife框架 】
APT简介 APT英文全称:Android annotation process tool是一种处理注释的工具,它对源代码文件进行检测找出其中的Annotation,使用Annotation进行额外的处理。 Annotation处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文…...

线程的基本概念
文章目录基础概念线程与进程什么是进程?什么是线程?进程和线程的区别:多线程什么是多线程?多线程的局限性串行、并行、并发同步异步、阻塞非阻塞线程的创建1、继承Thread类,重写run方法2、实现Runnable接口,…...
java面试题中常见名词注解
一.常见名词注解 1.mysql索引,索引数据结构,hash,二叉树,B树,B树,红黑树, mysql索引:帮助mysql高效获取数据的数据结构,通俗来说,数据库索引就好比一本书的…...
SpringAOP从入门到源码分析大全,学好AOP这一篇就够了(二)
文章目录系列文档索引四、Spring AOP的使用入门1、激活AspectJ模块(1)注解激活(2)XML激活2、创建 AspectJ 代理(了解)(1)编程方式创建 AspectJ 代理实例(2)XM…...

华为OD机试 - 斗地主(C++) | 附带编码思路 【2023】
刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…...

【存储】etcd的存储是如何实现的(3)-blotdb
前两篇分别介绍了etcd的存储模块以及mvcc模块。在存储模块中,提到了etcd kv存储backend是基于boltdb实现的,其在boltdb的基础上封装了读写事务,通过内存缓存批量将事务刷盘,提升整体的写入性能。botldb是etcd的真正的底层存储。本…...
基于MATLAB开发AUTOSAR软件应用层模块-part21.SR interface通信介绍(包括isupdated判断通信)
这篇文章我们介绍最后一种interface,即Sender-Receiver Interface,这种通信方式是autosar架构中最常用的的通信方式,即一个SWC发送数据,另一个SWC接收数据,实现数据交互。下边我们介绍下这篇文章主要介绍的内容: 目录如下: 如何配置SR interface,实现SR 通信介绍含有…...
Kotlin新手教程八(泛型)
一、泛型 1.泛型类的创建与实例化 kotlin中泛型类的创建与实例化与Java中相似: class A<T>(t:T){var valuet }fun main() {var a:A<Int> A<Int>(11) }Kotlin中存在类型推断,所以创建实例可以写成: var aA(11)2.泛型约束…...

性能测试知多少?怎样开展性能测试
看到好多新手,在性能需求模糊的情况下,随便找一个性能测试工具,然后就开始进行性能测试了,在这种情况下得到的性能测试结果很难体现系统真实的能力,或者可能与系统真实的性能相距甚远。 与功能测试相比,性能…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...

uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...