[Spring AOP] 基于AspectJ的@AfterReturning注释示例=

环境 :系统开发过程中,我们都曾实现过将系统元数据或字典表添加到缓存中,以便程序调用,减少数据库访问IO。

问题 :在用户通过前端页面更新系统字典表时,需手工刷新系统缓存,操作很不友好。

解决方案 :监听持久层DAO方法的调用,对于目标表的insert,update,delete操作进行相应的系统缓存更新。

 

示例环境 :Spring2.5 + iBatis + AspectJ

参考书目 :Spring 2.5 Aspect-Oriented Programming

 

Spring 2.5 Aspect-Oriented Programming

 

Spring AOP自动代理的XML配置

 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <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 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  3. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
  4.   
  5.     <aop:aspectj-autoproxy/>   
  6.   
  7. </beans>  
 

被监测类的代码:

 

Java代码   收藏代码
  1. public interface ScDbInfoDAO {  
  2.   
  3.     BigDecimal insert(ScDbInfo record);  
  4.   
  5.     int updateByPrimaryKey(ScDbInfo record);  
  6.   
  7.     int updateByPrimaryKeySelective(ScDbInfo record);  
  8.   
  9.     List selectByExample(ScDbInfoExample example, String orderByClause);  
  10.   
  11.     List selectByExample(ScDbInfoExample example);  
  12.   
  13.     ScDbInfo selectByPrimaryKey(BigDecimal dbId);  
  14.   
  15.     int deleteByExample(ScDbInfoExample example);  
  16.   
  17.     int deleteByPrimaryKey(BigDecimal dbId);  
  18.   
  19.     int selectCountByExample(ScDbInfoExample example);  
  20.   
  21. }  

 

然后是AspectJ实现:

 

Java代码   收藏代码
  1. import org.apache.log4j.Logger;  
  2. import org.aspectj.lang.JoinPoint;  
  3. import org.aspectj.lang.Signature;  
  4. import org.aspectj.lang.annotation.AfterReturning;  
  5. import org.aspectj.lang.annotation.Aspect;  
  6. import org.springframework.stereotype.Service;  
  7.   
  8. /** 
  9.  * @author seraph 
  10.  *  
  11.  */  
  12. @Service  
  13. @Aspect  
  14. public class JdbcSourceInterceptor {  
  15.   
  16.     private static final Logger log = Logger.getLogger(JdbcSourceInterceptor.class);  
  17.   
  18.     @AfterReturning(value="execution(* com.longtop.data.switching.db.dao.ScDbInfoDAO.*(..))", argNames="rtv", returning="rtv")  
  19.     public void afterInsertMethod(JoinPoint jp, Object rtv) throws Throwable {  
  20.   
  21.         Signature signature = jp.getSignature();  
  22.         log.debug("DeclaringType:" + signature.getDeclaringType());   
  23.         log.debug("DeclaringTypeName:" + signature.getDeclaringTypeName());  
  24.         log.debug("Modifiers:" + signature.getModifiers());  
  25.         log.debug("Name:" + signature.getName());  
  26.         log.debug("LongString:" + signature.toLongString());  
  27.         log.debug("ShortString:" + signature.toShortString());  
  28.   
  29.         for (int i = 0; i < jp.getArgs().length; i++) {  
  30.             Object arg = jp.getArgs()[i];  
  31.             if(null != arg) {  
  32.                 log.debug("Args:" + arg.toString());   
  33.             }  
  34.         }  
  35.   
  36.         log.debug("Return:" + rtv);   
  37.     }  
  38.   
  39. }  

 

运行时的监测日志:

 

Java代码   收藏代码
  1. JdbcSourceInterceptor  - DeclaringType:class dao.impl.ScDbInfoDAOImpl  
  2. JdbcSourceInterceptor  - DeclaringTypeName:dao.impl.ScDbInfoDAOImpl  
  3. JdbcSourceInterceptor  - Modifiers:1  
  4. JdbcSourceInterceptor  - Name:selectByPrimaryKey  
  5. JdbcSourceInterceptor  - LongString:ScDbInfoDAOImpl.selectByPrimaryKey(BigDecimal)  
  6. JdbcSourceInterceptor  - ShortString:selectByPrimaryKey  
  7. JdbcSourceInterceptor  - Args:1  
  8. JdbcSourceInterceptor  - Return:ScDbInfo: [dbId=1, dbName=oracle, dbDesc=oracle驱动, dbType=2, dbIp=10.1.7.19, dbPortNo=1521, dbInstName=dc, dbUserName=cgst, dbPwd=cgst, maxConnNum=100, minConnNum=20, initConnNum=26]  
 

通过以上的日志我们可以看出,@AfterReturning注释AOP中,通过JoinPoint和返回参数我们可以得到类运行时的所有相关信息,如通过方法名我们可以鉴别出是insert, update还是delete操作,针对不同的操作实现不同的处理方法,如调用缓存的add(),remove(),refresh()方法。我们还可以获取方法的调用参数及返回值,这极大的方便了我们对原业务逻辑的AOP处理。

 

一些相关概念:

  • Aspect - 切面
  • Pointcut - 切入点
  • Joinpoint - 连接点
  • Pointcut Designators (PCD)

Spring AOP中, 切入点(Pointcut)注释符在使用execution方法时以下的连接点(joinpoint)是可用的。
•    execution

•    within

•    this
•    target

•    args

•    @target

•    @args
•    @within

•    @annotation

•    bean

 

以下的切入点(pointcut)仅支持基于XML的Spring AOP配置,不支持AspectJ注释形式。如使用将会导致IllegalArgumentException异常。他们是:

•    call

•    get

•    set

•    preinitialization

•    staticinitialization
•    initialization

•    handler

•    adviceexecution

•    withincode
•    cflow

•    cflowbelow

•    if

•    @this

•    @withincode

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AOP(面向切面编程)中,@After和@AfterReturning是两个常用的注解,用于在目标方法执行后执行一些逻辑。它们的区别如下: 1. @After注解: - @After注解标记的方法会在目标方法执行后无论是否发生异常都会被执行。 - 它类似于finally代码块,无论目标方法是否成功执行,都会执行@After注解标记的方法。 - 通常用于释放资源或进行清理工作。 2. @AfterReturning注解: - @AfterReturning注解标记的方法只会在目标方法成功执行后被执行,不会在目标方法发生异常时执行。 - 它可以获取到目标方法的返回值作为参数。 - 通常用于处理目标方法的返回结果。 下面是一个示例: ```java @Aspect @Component public class LoggingAspect { @After(value = "execution(* com.example.MyService.doSomething(..))") public void afterMethod(JoinPoint joinPoint) { System.out.println("执行目标方法后执行@After注解标记的方法"); } @AfterReturning(value = "execution(* com.example.MyService.doSomething(..))", returning = "result") public void afterReturningMethod(JoinPoint joinPoint, Object result) { System.out.println("目标方法返回值:" + result); System.out.println("执行目标方法成功后执行@AfterReturning注解标记的方法"); } } ``` 在上述示例中,`@After`注解标记的`afterMethod`方法会在目标方法`doSomething`执行后无论是否发生异常都会被执行。而`@AfterReturning`注解标记的`afterReturningMethod`方法只会在目标方法执行成功并且返回结果时执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值