日期:2014-05-17  浏览次数:20979 次

[Spring AOP] 基于AspectJ的@AfterReturning注释示例(附参考书目)

注释形式的AOP编程,便利的实现了运行时对类及其方法的监控及干预,使生活变得更美好。 —— 《Seraph川上曰》

?

环境系统开发过程中,我们都曾实现过将系统元数据或字典表添加到缓存中,以便程序调用,减少数据库访问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 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <aop:aspectj-autoproxy/> 

</beans>
?

被监测类的代码:

?

public interface ScDbInfoDAO {

    BigDecimal insert(ScDbInfo record);

    int updateByPrimaryKey(ScDbInfo record);

    int updateByPrimaryKeySelective(ScDbInfo record);

    List selectByExample(ScDbInfoExample example, String orderByClause);

    List selectByExample(ScDbInfoExample example);

    ScDbInfo selectByPrimaryKey(BigDecimal dbId);

    int deleteByExample(ScDbInfoExample example);

    int deleteByPrimaryKey(BigDecimal dbId);

    int selectCountByExample(ScDbInfoExample example);

}

?

然后是AspectJ实现:

?

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;

/**
 * @author seraph
 * 
 */
@Service
@Aspect
public class JdbcSourceInterceptor {

	private static final Logger log = Logger.getLogger(JdbcSourceInterceptor.class);

	@AfterReturning(value="execution(* com.longtop.data.switching.db.dao.ScDbInfoDAO.*(..))", argNames="rtv", returning="rtv")
	public void afterInsertMethod(JoinPoint jp, Object rtv) throws Throwable {

		Signature signature = jp.getSignature();
		log.debug("DeclaringType:" + signature.getDeclaringType()); 
		log.debug("DeclaringTypeName:" + signature.getDeclaringTypeName());
		log.debug("Modifiers:" + signature.getModifiers());
		log.debug("Name:" + signature.getName());
		log.debug("LongString:" + signature.toLongString());
		log.debug("ShortString:" + signature.toShortString());

		for (int i = 0; i < jp.getArgs().length; i++) {
			Object arg = jp.getArgs()[i];
			if(null != arg) {
				log.debug("Args:" + arg.toString()); 
			}
		}

        log.debug("Return:" + rtv); 
    }

}

?

运行时的监测日志:

?

JdbcSourceInterceptor  - DeclaringType:class dao.impl.ScDbInfoDAOImpl
JdbcSourceInterceptor  - DeclaringTypeName:dao.impl.ScDbInfoDAOImpl
JdbcSourceInterceptor  - Modifiers:1
JdbcSourceInterceptor  - Name:selectByPrimaryKey
JdbcSourceInterceptor  - LongString:ScDbInfoDAOImpl.selectByPrimaryKey(BigDecimal)
JdbcSourceInt