1.如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志
2.springbootaopï¼
3.SpringBoot基础之AOP&AspectJ
4.SpringBoot的AOP(@aspect注解)的简单使用
5.Springboot整合AOP和注解,实现丰富的切面功能
如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志
首先,我们来观察一下切面日志的输出效果。在了解实现方法之前,中国海关燕窝溯源码查询我们可以看到每个请求的开始与结束都很清晰,同时打印了以下参数:
效果看起来还不错,接下来我们将一步步实现它。
二、添加 AOP Maven 依赖
在项目的 pom.xml 文件中,添加以下依赖:
三、自定义日志注解
接下来,我们来定义一个日志注解,如下所示:
源代码如下:
到这里,一个完整的自定义注解就定义完成了。
四、配置 AOP 切面
在配置 AOP 切面之前,我们需要了解一些 aspectj 相关注解的作用。
定义好切点后,我们可以围绕这个切点进行操作。接下来,VLC AVS 版源码定义一个 WebLogAspect.java 切面类,并声明一个切点。
然后,定义 @Around 环绕,用于何时执行切点。
接下来,看看 @Before 方法。
最后,用 @After 来做收尾。在每个接口的最后,打印日志结束标志。到这里,切面相关的代码就完成了。
五、如何使用?
因为我们的切点是自定义注解 @WebLog,所以我们只需要在 Controller 控制器的每个接口方法添加 @WebLog 注解即可。如果我们不想某个接口打印出入参日志,可以不加注解。
六、文件上传是否有效?
对于文件上传,不论是android案例源码汇总单文件上传还是多文件上传,切面日志都运行良好。有兴趣的小伙伴可以尝试一下。
七、如何在开发环境和测试环境中使用?
对于性能要求较高的应用,我们可以在开发环境或测试环境中使用,而不在生产环境中打印日志。我们只需为切面添加 @Profile 即可。
八、如何指定多切面的优先级?
如果我们服务中定义了多个切面,比如针对 Web 层接口,我们不仅想要打印日志,还要校验 token 等。我们可以通过 @Order(i) 注解来指定优先级。i 值越小,优先级越高。
springbootaopï¼
springbootaopèæ¶é¿
1ãä¸ä¸ªè±0.1ç§ï¼ä¸ªå°±1ç§ï¼ä¸ªå°±ç§äºâ¦ä»¥æ¤ç±»æ¨ï¼è¿ä¸ç¹å°±æ¯æ容ææ³æç½çå°æ¹äºãspringbootçèªå¨é ç½®ãèªå¨é ç½®æ¯springbootçä¸ä¸ªç¹è²ï¼ä½æ¯ä¹æ¯å®å¯å¨æ ¢çä¸ä¸ªå¼ç ã
2ãæè§å¾æ¯ä¸å¯è½ç¡®ä¿3ç§çï¼å ä¸è¯´ç¨åºæ¬èº«ï¼ä»æ¥æ¶è¯·æ±ï¼å°è¿å ¥åé¢ï¼å°åé¢å¤çï¼æåè¿åæ°æ®è¿ä¸è¿ç¨ï¼è¿è¡å®å°±éè¦èè´¹ä¸å®çæ¶é´ãèä¸æçä½ ç线ç¨æ± 深度åªæï¼é«å¹¶åä¸ï¼å¾å®¹æåºç°èµæºæ¢å¤ºã
3ãå®æ¶ä»»å¡é»è®¤æ¯å线ç¨çï¼å¦æ认为æç»æ¶é´è¾é¿ï¼å°±ä¼å°åé¢çå®æ¶ä»»å¡æ延ï¼å¯¼è´ä¸¢å¤±ä»»å¡ã
4ãç½ç»ä¸ç¨³å®å¯¼è´çãæå¡å¨springboot对ç½ç»çè¦æ±æ¯å¾é«çï¼å¨æ¥è¯¢æ¶éè¦ä¿æç½ç»çæµç ï¼å¦åæ¥è¯¢çé度ä¼ä¸ç¨³å®ãSpringBootæ¯ä¸ä¸ªæ¡æ¶ï¼ä¸ç§å ¨æ°çç¼ç¨è§èï¼ä»ç产çç®åäºæ¡æ¶ç使ç¨ã
5ãå¯ä»¥æ¿å°åå§çHTTP请æ±åååºçä¿¡æ¯ï¼ä¹å¯ä»¥æ¿å°ä½ çæ£å¤ç请æ±æ¹æ³çä¿¡æ¯ï¼ä¹å¯ä»¥ä¼ è¿åæ°çé£ä¸ªå¼ãå®ç°Filteræ¥å£å®ç°HandlerInterceptoræ¥å£ï¼ç¶åé ç½®è¿Springã
6ã)ä¸è¦è°è®º1)æ¥å¤©ãæ ¸å¿çiocãaopææ¯åioc解è¦ä½¿å¾ä»£ç éç¨æ§åå¯ç»´æ¤æ§å¤§å¤§æé«ãaopæä¾äºå沿çç¼ç¨ï¼è¿ä¹æé«äºç产çã2)springmvcï¼ç¸æ¯struts2çmvcæ¡æ¶ï¼ä¸æstruts2æé£ä¹å¤å®å ¨æ¼æ´ï¼å°±æ¯ç±»æ¦æªã
springbootå¨ææ·»å aopåé¢å¼å ¥aopçstarterï¼ç¬¬ä¸æ¥ï¼ç¬¬äºæ¥ï¼jarå æä¹åï¼åªéè¦å®ç°å¯¹åºçåé¢æ¹æ³å°±è¡äºé常ææ¹æ³åæ¦æªï¼æ¹æ³åæ¦æªï¼ä»¥åå¼å¸¸æ¦æªãéè¿å¨è¿äºæ¦æªä¸ç¼åèªå·±çä¸å¡å¤çï¼å¯ä»¥è¾¾å°ç¹å®çéæ±ã
å¨å建AOP代çä¹åéè¦æç¸å ³çåé¢é 置解ææä¸é¢ç±»å¾ä¸çæ¥å£åç±»ç对象ï¼å¯¹äºProxyFactoryBeanæ¥è¯´ï¼æ²¡æè¿ä¸ªè¿ç¨ï¼å 为è¿ç§æ¹å¼ä¸ä¸è½ä½¿ç¨åç¹ã
å¯ä»¥çä¸é¢å ³äºAOPçé»è®¤é ç½®å±æ§ï¼å ¶ä¸spring.aop.autoå±æ§é»è®¤æ¯å¼å¯çï¼ä¹å°±æ¯è¯´åªè¦å¼å ¥äºAOPä¾èµåï¼é»è®¤å·²ç»å¢å äº@EnableAspectJAutoProxyã
AOPåé¢åæ³ä¸æ³å没æå ³ç³»ï¼å ³é®è¿æ¯@Pointcutåå¾å¯¹ä¸å¯¹ã
springbootæä¹æ·»å ä¸ä¸ªaopäºä»¶
å¼å ¥aopçstarterï¼ç¬¬ä¸æ¥ï¼ç¬¬äºæ¥ï¼jarå æä¹åï¼åªéè¦å®ç°å¯¹åºçåé¢æ¹æ³å°±è¡äºé常ææ¹æ³åæ¦æªï¼æ¹æ³åæ¦æªï¼ä»¥åå¼å¸¸æ¦æªãéè¿å¨è¿äºæ¦æªä¸ç¼åèªå·±çä¸å¡å¤çï¼å¯ä»¥è¾¾å°ç¹å®çéæ±ã
å¨springBootä¸ï¼åªéè¦å å ¥POMå°±å¯ä»¥äºï¼é å注解使ç¨å³å¯ãæ¥ä¸æ¥å°±æ¯äºå¡çæ§å¶äºãé¦å äºå¡æå å¤§ä¼ æå±æ§ï¼å ¶ä¸æ常è§çï¼ç¨å¾æå¤å°±PROPAGATION_REQUIREDãPROPAGATION_REQUIRES_NEWãPROPAGATION_NESTEDè¿ä¸ç§ã
åè¨ï¼è¯¥å客主è¦æ¯è®°å½èªå·±å¦ä¹ çè¿ç¨ï¼æ¹ä¾¿ä»¥åæ¥çï¼å½ç¶ä¹å¸æè½å¤å¸®å°å¤§å®¶ãåè®°ï¼æ¬æ¬¡å享å°æ¤ç»æï¼æ¬äººæ°´å¹³æéï¼é¾å æé误æéæ¼ä¹å¤ï¼æ大家ææ£åè° è§£ï¼æ¬¢è¿è¯è®ºçè¨ã
SpringBootæ ¸å¿åç:èªå¨é ç½®ãäºä»¶é©±å¨ãCondition1ãSpringBootå¨å¯å¨çæ¶åä»ç±»è·¯å¾ä¸çMETA-INF/spring.factoriesä¸è·åEnableAutoConfigurationæå®çå¼å°è¿äºå¼ä½ä¸ºèªå¨é ç½®ç±»å¯¼å ¥å®¹å¨ï¼èªå¨é 置类就çæï¼å¸®æ们è¿è¡èªå¨é 置工ä½ã
2ãSpringæ¯æJavaé ç½®åXMLé ç½®ï¼ä»ä»¬ä¸ºåºç¨ç¨åºå¼å¯äºç¹å®çç¹æ§ååè½ï¼SpringBootå®ç°äºèªå¨é ç½®ï¼å¯ä»¥åå°é ç½®è´æ ã
3ãæ¹æ³/æ¥éª¤SpringBootå¯å¨çæ¶åå 载主é 置类ï¼å¼å¯äºèªå¨é ç½®åè½@EnableAutoConfigurationã请ç¹å»è¾å ¥å¾çæè¿°EnableAutoConfigurationçä½ç¨æ¯å©ç¨AutoConfigurationImportSelectorç»å®¹å¨ä¸å¯¼å ¥ä¸äºç»ä»¶ã
4ã第ä¸æ¥ï¼å¯å¨ä¸ä¸ªæ°çSpringBoot项ç®å©ç¨å¯å¨.spring.ioå建ä¸ä¸ªâç½ç»â项ç®ãå¨âä¾èµé¡¹â对è¯æ¡ä¸æ索并添å âwebâä¾èµé¡¹ï¼å¦å±å¹æªå¾æ示ãç¹å»âçæâæé®ï¼ä¸è½½zipï¼ç¶åå°å ¶è§£å缩å°è®¡ç®æºä¸çæ件夹ä¸ã
5ãå建ä¸ä¸ªSpringApplication对象æ¶ï¼ä¼è°ç¨å®èªå·±çinitializeæ¹æ³æ§è¡æ ¸å¿runæ¹æ³åå§åinitializeæ¹æ³æ§è¡å®ä¹åï¼ä¼è°ç¨runæ¹æ³ï¼å¼å§å¯å¨SpringBootã
springbootaop解å³æ¾ä¸å°jarä¸æ件å°åä½æ件æ¾å¨javaç¨åºresourcesèµæºæ件ä¸å è½½ï¼Thread.currentThread().getContextClassLoader().getResource().getPath()è¿ç§æ¹å¼å¯ä»¥æ£ç¡®è·ååä½æ件路å¾ã
æ°å»ºSpringBoot项ç®åï¼é¡¹ç®æ£å¸¸è¿è¡ï¼ä½æ¯pom.xmlæ件æ示âProjectorg.springframework.bootï¼spring-boot-starter-parentï¼5notfoundâãåºç°è¿ç§é®é¢ï¼æ¯ç±äºå¨å½åçä»åºä¸æ¾ä¸å°æå®ççæ¬Jarå ã
ä¸è¬æ两ç§æ¹æ³ã1ï¼å°æ¬å°jarå å®è£ å¨æ¬å°mavenåºï¼2ï¼å°æ¬å°jarå æ¾å ¥é¡¹ç®ç®å½ä¸ã
æ没æç¨è¿springclasspathï¼applicationContext.xmlè¿ä¸ªé ç½®ï¼å¦ä½ å¾ä¸æ示ï¼æ¾å¨äºresourcesä¸ï¼é£ä¹å¨å·¥ç¨ä¸æ¯å¯ä»¥è¿è¡çï¼åªæ¯æå å°jarä¸ä»¥åæ¾ä¸å°ï¼æå ç¹çæµresourcesä¸çé ç½®æ件ï¼æ²¡ææ¾å è¿å»ã
ç±äºSpringBootæå åï¼é»è®¤æ¯ä¸è½å è½½å¤é¨çjaræ件ï¼åªè½é»è®¤å è½½ymlæ件ã
SpringBoot基础之AOP&AspectJ
在SpringBoot中,AOP与AspectJ是关键的依赖,用于实现面向切面编程,使得代码逻辑清晰且易于维护。以日志切面为例,通过@Before("execution( (..))")注解,微商宠儿源码可以实现对某个方法的前置处理,这里的(..)代表同一包路径下的方法。具体应用中,execution( (..))可以精确到指定的返回类型、方法名与参数,例如@Before("execution( hello())")则表示匹配带有一个任意类型参数且返回类型无限制的hello方法。
通过配置Pointcut,可以替换原有逻辑,实现更灵活的切点控制。在Spring中,可以利用AspectJ的特性,通过EnableLoadTimeWeaving功能动态加载切面,增强系统的可扩展性。
Spring提供了多种内置的拦截器,如CustomizableTraceInterceptor、SimpleTraceInterceptor、DebugInterceptor、PerformanceMonitorInterceptor、AsyncExecutionInterceptor与ConcurrencyThrottleInterceptor等,分别用于日志记录、性能监控、头像签名设计源码异步调用与并发控制。例如,PerformanceMonitorInterceptor使用StopWatch进行精确到毫秒级的性能测量,适合于对性能敏感的应用场景。
在处理异常逻辑时,SpringBoot提供了CatchInterceptor,允许缓存方法调用结果,避免重复计算,简化了缓存逻辑的编写。
SpringBoot中还集成了CircuitBreaker机制,用于处理网络或服务间的不稳定问题。通过监控请求响应情况,当发现异常时,CircuitBreaker会进入断路状态,避免系统因不稳定服务而崩溃。例如,在调用远程服务时,如果连续失败达到一定次数,则触发断路,后续请求直接返回错误信息,直到服务恢复。
综上所述,SpringBoot的AOP与AspectJ框架提供了丰富的功能,从日志记录、性能监控到异常处理与服务间通信优化,都得以高效实现,大大增强了应用的健壮性与可维护性。通过灵活配置与利用内置的拦截器,开发者可以更专注于业务逻辑的实现,而将复杂度较高的系统维护工作交给框架处理。
SpringBoot的AOP(@aspect注解)的简单使用
在SpringBoot中,利用AOP(面向切面编程)进行代码组织,有助于提高代码复用性和降低耦合度。在具体实现时,需要关注如何导入依赖,创建并使用Aspect类,以及理解关键注解和类的运用。
首先,导入Spring AOP的依赖包至关重要。这一步确保了Spring容器能够识别并管理切面类。
其次,直接编写Aspect类是创建切面的一种方法。在类中定义切点(Pointcut),通常包括方法签名和表达式两个部分。方法签名用于定义匹配的类和方法,表达式则描述了在何时执行增强代码。重要的是,方法签名需要是公共且无返回值的,用来避免不必要的代码执行。
为了便于理解,可以使用注解来简化Pointcut的定义。常用的注解包括@Aspect(声明切面类)、@Component(整合到Spring管理中)、@Pointcut(定义切点)、以及针对增强操作的注解,如@Before、@AfterReturning、@After和@AfterThrowing。
在实际开发中,Spring AOP提供了强大的功能,如获取JoinPoint以访问被代理类、方法和参数,以及使用RequestAttributes来操作HttpServletRequest对象。这些功能常用于实现如权限校验、日志记录等需求,原理基于动态代理机制。
常用的注解包括@Aspect用于声明切面类,@Pointcut用于定义切点,以及针对不同增强操作的注解,如@Around、@Before、@After、@AfterReturning和@AfterThrowing。
在SpringBoot中,AOP的应用通常围绕具体需求展开,如实现权限校验、日志记录等。AOP通过定义切点和增强策略,使得开发人员可以在不修改原有代码的情况下,实现特定的行为增强。
举例说明,假设我们想要在所有控制器方法执行前后添加日志记录。可以通过创建一个Aspect类,定义切点和相应的增强逻辑,然后在控制器类上应用这个切面。通过这种方式,实现了代码的解耦和可重用性。
总结来说,SpringBoot中的AOP提供了强大的功能,通过合理的切面设计和注解使用,可以有效地提高代码的可维护性和扩展性。使用@aspect注解进行简单使用,主要关注切点定义、增强策略的实现以及依赖的正确导入,即可在项目中灵活应用AOP技术。
Springboot整合AOP和注解,实现丰富的切面功能
在之前的文章《Spring AOP与AspectJ的应用详解》中,我们已经探讨了AOP的基本使用。本文将深入讲解如何结合注解,进一步提升AOP的灵活性。我们以实现一个简单的计时功能为例,来展示这一过程。
首先,我们创建一个自定义注解,为后续的切面处理做准备:
<!-- 注解定义 -->
然后,在一个Service类中,我们应用这个注解到需要计时的方法:
<!-- Service中的方法 -->
这个方法会被控制器调用,进而触发我们的AOP处理:
<!-- 控制器调用 -->
关键在于实现切面,利用Spring的@Around注解来识别带有我们自定义注解的方法。表达式如下,务必确保其准确性,以避免识别错误和潜在的多次调用问题(更多细节可参考Stackoverflow):
<!-- 切面实现 -->
@Around("@annotation(com.pkslow.springboot.aop.PkslowLogTime) && execution(* *(..))")
这里借助Spring的StopWatch来记录方法执行时间。
接下来,我们进行测试。通过Maven构建项目:
<!-- 测试阶段 -->
在日志中,你会看到切面织入的痕迹:
<!-- 日志输出 -->
启动应用并访问相关接口,你会看到计时信息的实时记录:
总的来说,通过注解与AOP的结合,我们可以轻松实现各种功能,并且通过注解的参数化和组合,进一步增强了灵活性。如果你对这个例子感兴趣,可以在GitHub上查看详细代码:<a href="github.com/LarryDpk/pks...">github.com/LarryDpk/pks...
2024-12-27 15:58
2024-12-27 15:45
2024-12-27 15:08
2024-12-27 14:53
2024-12-27 14:05
2024-12-27 14:00