详解Spring Aop实例之AspectJ注解配置

发布时间 - 2026-01-11 00:31:14    点击率:

上篇《Spring Aop实例之xml配置》中,讲解了xml配置方式,今天来说说AspectJ注解方式去配置spring aop。

依旧采用的jdk,接口和实现类代码请参考上篇博文。主要是将Aspect类分享一下:

package com.tgb.aop; 
 
import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.After; 
import org.aspectj.lang.annotation.AfterReturning; 
import org.aspectj.lang.annotation.AfterThrowing; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Before; 
import org.aspectj.lang.annotation.DeclareParents; 
import org.aspectj.lang.annotation.Pointcut; 
 
/** 
 * 测试after,before,around,throwing,returning Advice. 
 * @author Admin 
 * 
 */ 
@Aspect 
public class AspceJAdvice { 
 
 /** 
  * Pointcut 
  * 定义Pointcut,Pointcut的名称为aspectjMethod(),此方法没有返回值和参数 
  * 该方法就是一个标识,不进行调用 
  */ 
 @Pointcut("execution(* find*(..))") 
 private void aspectjMethod(){}; 
  
 /** 
  * Before 
  * 在核心业务执行前执行,不能阻止核心业务的调用。 
  * @param joinPoint 
  */ 
 @Before("aspectjMethod()") 
 public void beforeAdvice(JoinPoint joinPoint) { 
  System.out.println("-----beforeAdvice().invoke-----"); 
  System.out.println(" 此处意在执行核心业务逻辑前,做一些安全性的判断等等"); 
  System.out.println(" 可通过joinPoint来获取所需要的内容"); 
  System.out.println("-----End of beforeAdvice()------"); 
 } 
  
 /** 
  * After 
  * 核心业务逻辑退出后(包括正常执行结束和异常退出),执行此Advice 
  * @param joinPoint 
  */ 
 @After(value = "aspectjMethod()") 
 public void afterAdvice(JoinPoint joinPoint) { 
  System.out.println("-----afterAdvice().invoke-----"); 
  System.out.println(" 此处意在执行核心业务逻辑之后,做一些日志记录操作等等"); 
  System.out.println(" 可通过joinPoint来获取所需要的内容"); 
  System.out.println("-----End of afterAdvice()------"); 
 } 
 
 /** 
  * Around 
  * 手动控制调用核心业务逻辑,以及调用前和调用后的处理, 
  * 
  * 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 
  * 执行完AfterAdvice,再转到ThrowingAdvice 
  * @param pjp 
  * @return 
  * @throws Throwable 
  */ 
 @Around(value = "aspectjMethod()") 
 public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { 
  System.out.println("-----aroundAdvice().invoke-----"); 
  System.out.println(" 此处可以做类似于Before Advice的事情"); 
   
  //调用核心逻辑 
  Object retVal = pjp.proceed(); 
  System.out.println(" 此处可以做类似于After Advice的事情"); 
  System.out.println("-----End of aroundAdvice()------"); 
  return retVal; 
 } 
  
 /** 
  * AfterReturning 
  * 核心业务逻辑调用正常退出后,不管是否有返回值,正常退出后,均执行此Advice 
  * @param joinPoint 
  */ 
 @AfterReturning(value = "aspectjMethod()", returning = "retVal") 
 public void afterReturningAdvice(JoinPoint joinPoint, String retVal) { 
  System.out.println("-----afterReturningAdvice().invoke-----"); 
  System.out.println("Return Value: " + retVal); 
  System.out.println(" 此处可以对返回值做进一步处理"); 
  System.out.println(" 可通过joinPoint来获取所需要的内容"); 
  System.out.println("-----End of afterReturningAdvice()------"); 
 } 
  
 /** 
  * 核心业务逻辑调用异常退出后,执行此Advice,处理错误信息 
  * 
  * 注意:执行顺序在Around Advice之后 
  * @param joinPoint 
  * @param ex 
  */ 
 @AfterThrowing(value = "aspectjMethod()", throwing = "ex") 
 public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) { 
  System.out.println("-----afterThrowingAdvice().invoke-----"); 
  System.out.println(" 错误信息:"+ex.getMessage()); 
  System.out.println(" 此处意在执行核心业务逻辑出错时,捕获异常,并可做一些日志记录操作等等"); 
  System.out.println(" 可通过joinPoint来获取所需要的内容"); 
  System.out.println("-----End of afterThrowingAdvice()------"); 
 } 
} 

application-config.xml中,只需要配置业务逻辑bean和Aspect bean,并启用Aspect注解即可:

<?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" 
   xmlns:tx="http://www.springframework.org/schema/tx" 
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> 
    
 <!-- 启用AspectJ对Annotation的支持 -->   
 <aop:aspectj-autoproxy/>    
  
 <bean id="userManager" class="com.tgb.aop.UserManagerImpl"/> 
 <bean id="aspcejHandler" class="com.tgb.aop.AspceJAdvice"/> 
  
</beans> 

 结果如图:

通过测试的发现AroundAdvice、BeforeAdvice、AfterAdvice、ReturningAdvice的执行顺序是根据注解的顺序而定的。但是有时候修改了顺序,结果却没有变化,可能是缓存的缘故。前几天我也遇到了这样的问题,不过今天再测试了一下,发现执行顺序又跟注解的顺序一致了。

 xml 和 Annotation 注解都可以作为配置项,对Spring AoP进行配置管理,那么它们各自都有什么优缺点呢?

首先说说 xml 。目前 web 应用中几乎都使用 xml 作为配置项,例如我们常用的框架 Struts、Spring、hibernate 等等都采用 xml 作为配置。xml 之所以这么流行,是因为它的很多优点是其它技术的配置所无法替代的:

  1. xml 作为可扩展标记语言最大的优势在于开发者能够为软件量身定制适用的标记,使代码更加通俗易懂。
  2. 利用 xml 配置能使软件更具扩展性。例如 Spring 将 class 间的依赖配置在 xml 中,最大限度地提升应用的可扩展性。
  3. 具有成熟的验证机制确保程序正确性。利用 Schema 或 DTD 可以对 xml 的正确性进行验证,避免了非法的配置导致应用程序出错。
  4. 修改配置而无需变动现有程序。

虽然有如此多的好处,但毕竟没有什么万能的东西,xml 也有自身的缺点。

  1. 需要解析工具或类库的支持。
  2. 解析 xml 势必会影响应用程序性能,占用系统资源。
  3. 配置文件过多导致管理变得困难。
  4. 编译期无法对其配置项的正确性进行验证,或要查错只能在运行期。
  5. IDE 无法验证配置项的正确无能为力。
  6. 查错变得困难。往往配置的一个手误导致莫名其妙的错误。
  7. 开发人员不得不同时维护代码和配置文件,开发效率变得低下。
  8. 配置项与代码间存在潜规则。改变了任何一方都有可能影响另外一方。

让我们来看看 Annotation 的优点。

  1. 保存在 class 文件中,降低维护成本。
  2. 无需工具支持,无需解析。
  3. 编译期验证正确性,查错变得容易。
  4. 提升开发效率。

同样 Annotation 也不是万能的,它也有很多缺点。

  1. 若要对配置项进行修改,不得不修改 Java 文件,重新编译打包应用。
  2. 配置项编码在 Java 文件中,可扩展性差。

总结:没有一个事物是万能的,同样 xml 和 Java Annotation 都有各自的优缺点。通过以上对比,细心的读者可能已经发现它们的优缺点恰恰是互补的。xml 的强项是 Annotation 所不具备的,而 Annotation 的优势也是 xml 所欠缺的。这也正是时下流行的 xml + Annotation 配置的原因所在。平衡才是王道呀!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# spring aop aspectj  # spring aop与aspectj  # spring aspectj 注解  # 都有  # 可通过  # 所需要  # 返回值  # 类似于  # 错误信息  # 以对  # 查错  # 配置文件  # 应用程序  # 上篇  # 我也  # 也有  # 是因为  # 让我们  # 才是  # 有很多  # 没有什么  # 转到  # 这也 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 大连网站制作公司哪家好一点,大连买房网站哪个好?  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  南京网站制作费用,南京远驱官方网站?  如何在宝塔面板中创建新站点?  VIVO手机上del键无效OnKeyListener不响应的原因及解决方法  Laravel Session怎么存储_Laravel Session驱动配置详解  Laravel如何与Pusher实现实时通信?(WebSocket示例)  Python图片处理进阶教程_Pillow滤镜与图像增强  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  如何快速配置高效服务器建站软件?  Linux后台任务运行方法_nohup与&使用技巧【技巧】  Laravel如何保护应用免受CSRF攻击?(原理和示例)  如何在Windows 2008云服务器安全搭建网站?  Laravel如何实现用户注册和登录?(Auth脚手架指南)  ,南京靠谱的征婚网站?  Internet Explorer官网直接进入 IE浏览器在线体验版网址  如何挑选最适合建站的高性能VPS主机?  如何实现javascript表单验证_正则表达式有哪些实用技巧  html5怎么画眼睛_HT5用Canvas或SVG画眼球瞳孔加JS控制动态【绘制】  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  如何用低价快速搭建高质量网站?  Laravel怎么使用Intervention Image库处理图片上传和缩放  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  linux写shell需要注意的问题(必看)  Laravel storage目录权限问题_Laravel文件写入权限设置  免费网站制作appp,免费制作app哪个平台好?  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  详解Android——蓝牙技术 带你实现终端间数据传输  javascript如何操作浏览器历史记录_怎样实现无刷新导航  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭  西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?  如何快速搭建安全的FTP站点?  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  如何在七牛云存储上搭建网站并设置自定义域名?  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  如何在橙子建站中快速调整背景颜色?  如何在Windows服务器上快速搭建网站?  手机网站制作与建设方案,手机网站如何建设?  简历在线制作网站免费版,如何创建个人简历?  jquery插件bootstrapValidator表单验证详解  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  JavaScript模板引擎Template.js使用详解  详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点  Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  如何解决hover在ie6中的兼容性问题  大连 网站制作,大连天途有线官网?  如何快速建站并高效导出源代码?  laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法