news 2026/4/15 12:54:53

【Java基础】AOP与注解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Java基础】AOP与注解

一、注解

1、注解定义

注解本质上是一个实现了annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。通过反射获取注解时,返回的是Java运行时生成的动态代理对象。

// 定义注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public@interfaceMyAnnotation{Stringvalue()default"default";intcount()default0;}// 编译后:注解本质是一个接口,继承自AnnotationpublicinterfaceMyAnnotationextendsjava.lang.annotation.Annotation{Stringvalue();intcount();}

2、注解作用域和作用范围

2.1 作用域 (@Retention)

根据作用域,可以分为如下三类:

源码级:只在源码中存在,编译后会不会保留,(@Retention(RetentionPolicy.SOURCE))。

类文件级别注解:保留在.class文件中,但运行时不可见,(@Retention(RetentionPolicy.CLASS))。

运行时注解:保留在.class文件中,只有这个作用域可以通过反射在运行时访问(@Retention(RetentionPolicy.RUNTIME))。

2.2 作用范围

作用范围有方法、属性、类

二、AOP

1. 定义切面类

切面类需使用@Aspect标识,并纳入 Spring 容器管理:

@Aspect @Component @Slf4j public class CacheAspect { }

2. 定义切点(Pointcut)

切点用于描述哪些方法/类/连接点需要被拦截。


2.1 常见 Pointcut 表达式

2.1.1@annotation

匹配方法上标记了指定注解的连接点:

// 匹配所有带 @CacheAble 注解的方法 @Pointcut("@annotation(org.example.aop.CacheAble)") public void cacheAbleCut(){}

技巧
可在 Advice 入参中直接绑定注解对象:

@Around("cacheAbleCut() && @annotation(cacheAble)") public Object around(ProceedingJoinPoint jp, CacheAble cacheAble) { ... }

这样可以直接获取注解属性值,无需手动反射。


2.1.2execution

根据方法签名匹配:

// 匹配所有公共方法 @Pointcut("execution(public * *(..))") public void anyPublicMethod() {} // 匹配所有以 set 开头的方法 @Pointcut("execution(* set*(..))") public void anySetMethod() {} // 匹配 com.example.service 包下所有类的所有方法 @Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethods() {} // 匹配 UserDao 接口的所有实现方法 @Pointcut("execution(* com.example.dao.UserDao.*(..))") public void userDaoMethods() {} // 匹配返回值类型为 User 的方法 @Pointcut("execution(com.example.model.User *(..))") public void methodsReturningUser() {}

2.1.3@within@target

匹配类级别注解:

// 匹配带 @Service 注解类中的所有方法 @Pointcut("@within(org.springframework.stereotype.Service)") public void serviceAnnotationMethods() {} // 匹配目标对象带 @Repository 注解的连接点 @Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryAnnotationMethods() {}

区别:

  • @within→ 检查声明类是否有注解
  • @target→ 检查运行时目标类是否有注解(Spring 代理场景可能不同)

2.1.4 组合切点

支持&&(与)、||(或)、!(非):

// 在 service 包中且为公共方法 @Pointcut("serviceMethods() && anyPublicMethod()") public void servicePublicMethods() {} // service 包 或 dao 包方法 @Pointcut("serviceMethods() || daoMethods()") public void serviceOrDaoMethods() {} // 非事务性 service 方法 @Pointcut("serviceMethods() && !transactionalMethods()") public void serviceNonTransactionalMethods() {}

2.2 其他常用匹配方式

2.2.1args

绑定方法参数:

@Pointcut("execution(* com.example..*(..)) && args(userId,..)") public void methodWithUserIdArg(String userId) {}

Advice 可直接接收参数:

@Before("methodWithUserIdArg(userId)") public void logUser(String userId) { ... }
2.2.2this/target
  • this(proxy):绑定代理对象
  • target(obj):绑定真实目标对象
@Around("this(proxy) && target(service)") public Object around(ProceedingJoinPoint jp, Object proxy, MyService service) { ... }

3.定义切面

在 AOP 中,切面逻辑主要通过以下几种Advice来实现:

通知类型注解作用时机
前置通知@Before目标方法执行前
后置通知@After目标方法执行后(无论是否异常)
返回通知@AfterReturning目标方法成功返回后
异常通知@AfterThrowing目标方法抛出异常后
环绕通知@Around在目标方法前后都可执行,并可决定是否执行目标方法

​ 其中ProceedingJoinPoint是JoinPoint的子类,由于Around需要执行源方法,ProceedingJoinPoint针对@Around环绕通知提供了proceed()来调用源方法。

3.1 前置通知 @Before

@Before("cacheAbleCut()")publicvoidbeforeMethod(JoinPointjoinPoint){log.info("执行前置通知: 方法 = {}, 参数 = {}",joinPoint.getSignature().getName(),Arrays.toString(joinPoint.getArgs()));}

3.2 后置通知 @After

@After("cacheAbleCut()")publicvoidafterMethod(JoinPointjoinPoint){log.info("执行后置通知: 方法 = {}",joinPoint.getSignature().getName());}

3.3 返回通知 @AfterReturning

@AfterReturning(pointcut="cacheAbleCut()",returning="result")publicvoidafterReturning(JoinPointjoinPoint,Objectresult){log.info("方法 {} 成功返回,返回值 = {}",joinPoint.getSignature().getName(),result);}

3.4 异常通知 @AfterThrowing

@AfterThrowing(pointcut="cacheAbleCut()",throwing="ex")publicvoidafterThrowing(JoinPointjoinPoint,Throwableex){log.error("方法 {} 抛出异常: {}",joinPoint.getSignature().getName(),ex.getMessage(),ex);}

3.5 环绕通知 @Around

@Around是功能最强的通知,可以控制方法执行与否,并在执行前后做处理:

@Around("cacheAbleCut()")publicObjectaround(ProceedingJoinPointpjp)throwsThrowable{log.info("环绕通知开始 - 方法: {}",pjp.getSignature().getName());longstartTime=System.currentTimeMillis();// 执行目标方法Objectresult=pjp.proceed();longendTime=System.currentTimeMillis();log.info("环绕通知结束 - 耗时: {}ms",(endTime-startTime));// 返回的即最终方法执行后返回的结果,可以自定义随意返回returnresult;}
高级用法:绑定注解实例

如果希望直接在环绕通知的方法参数中获取到目标方法上的注解对象,可以这样写:

@Around("aopPoint() && @annotation(rateLimiterAccessInterceptor)")publicObjectdoRouter(ProceedingJoinPointjp,RateLimiterAccessInterceptorrateLimiterAccessInterceptor)throwsThrowable{log.info("限流检查: key={}, permits={}",rateLimiterAccessInterceptor.key(),rateLimiterAccessInterceptor.permits());returnjp.proceed();}

说明

  • && @annotation(rateLimiterAccessInterceptor)
    限定切点只匹配带有该注解的方法,并且将注解实例注入到参数中。
  • 方法参数RateLimiterAccessInterceptor rateLimiterAccessInterceptor
    直接就是方法上真实存在的注解对象,不需要手动反射getMethod()getAnnotation()

示例目标方法:

@RateLimiterAccessInterceptor(key="userLogin",permits=5)publicvoidlogin(Stringusername){// 登录逻辑}

执行时 AOP 会自动把@RateLimiterAccessInterceptor注解实例注入到doRouter()的第二个参数中。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 7:33:11

大数据处理中的数据隐私保护机制研究

大数据处理中的数据隐私保护机制研究关键词:大数据处理、数据隐私保护、加密技术、匿名化、差分隐私摘要:本文深入探讨大数据处理过程中数据隐私保护机制。通过阐述数据隐私保护的背景、核心概念,介绍相关算法原理与实际操作步骤,…

作者头像 李华
网站建设 2026/4/15 7:48:38

通俗理解多层感知机(MLP)

在当今的科技世界中,人工智能(AI)已经成为我们日常生活的一部分。从智能手机的语音助手,到自动驾驶汽车,再到医疗诊断系统,AI 的应用无处不在。而在这些先进技术的背后,多层感知机(M…

作者头像 李华
网站建设 2026/4/14 21:00:21

Spring Boot+MyBatis:用 PageHelper 实现 Oracle 12c 的 OFFSET 分页

在分页场景中,不同数据库的分页语法差异很大 —— 比如 MySQL 用LIMIT,而Oracle 12c 开始支持更灵活的OFFSET ... FETCH语法。今天结合 PageHelper,分享如何在 Spring Boot 中适配 Oracle 12c 的分页方式。 一、PageHelper 基础:…

作者头像 李华
网站建设 2026/4/16 11:07:32

CSV大文件处理全流程:数据清洗、去重与格式标准化深度实践

第一章 大文件处理核心挑战与解决方案1.1 内存优化策略处理GB级CSV文件时,传统方法如Pandas的read_csv()会引发内存溢出。我们采用以下解决方案:import csv from collections import defaultdictdef streaming_reader(file_path, chunk_size10000):with …

作者头像 李华
网站建设 2026/4/14 2:00:01

动态可视化报告制作:DeepSeek+Mermaid生成交互式流程图/甘特图

摘要: 在信息爆炸的时代,清晰、动态且交互式的数据可视化已成为高效沟通和决策的关键。本文将深入探讨如何结合先进的 AI 技术(以 DeepSeek 为代表)与轻量级图表描述语言 Mermaid,高效生成包含交互式流程图和甘特图的动…

作者头像 李华