Spring(11):使用@AspectJ 注解实现AOP日志打印与示例

2017/12/31

AspectJ,一个面向切面的框架。@AspectJ 是AspectJ版本5的新增功能,所以确保JDK是5.0以上版本,负责无法使用注解技术。

(1)Spring通过集成AspectJ实现了以注解定义切面,大大减少了配置文件的工作量。

(2)java的反射机制无法获取方法参数名,Spring还利用了字节码处理框架asm处理@AspectJ描述的方法参数名


下面通过一个实例演示:

【0】文件结构和jar包

Spring(11):使用@AspectJ 注解实现AOP日志打印与示例_第1张图片

图1


Spring(11):使用@AspectJ 注解实现AOP日志打印与示例_第2张图片

图2


【1】新建一个包(com\smbms\AopLog)新建两个增强类(UserserviceLogger、UserserviceLogger2):

UserserviceLogger.java:

package com.smbms.AopLog;

import java.util.Arrays;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class UserserviceLogger {
	private static final Logger log = Logger.getLogger(UserserviceLogger.class);
	//前置增强方法
	@Before("execution(* com.smbms.pojo..*.*(..))")
	public void before (JoinPoint jp) throws Throwable{
		log.info("***UserserviceLogger*********before:调用了"+jp.getTarget()+" 的"+jp.getSignature().getName()
				+" 方法。方法入参:"+Arrays.toString(jp.getArgs()));
		try{
			log.info("调用了 "+jp.getTarget()+" 的 "+jp.getSignature().getName()
			+" 方法。");
		}catch(Throwable e){
			log.error(jp.getSignature().getName()+" 方法发生异常: "+e);
			throw e;
		}finally{
			log.info(jp.getSignature().getName()+"方法执行结束");
		}
	}
	
	@AfterReturning(pointcut = "execution(* com.smbms.pojo..*.*(..))",
			        returning = "result")
	//后置增强方法
	public void after (JoinPoint jp,Object result) throws Throwable{
		log.info("****UserserviceLogger**********after:调用了 "+jp.getTarget()+" 的"+jp.getSignature().getName()
				+" 方法。方法入参:"+Arrays.toString(jp.getArgs())+result);
		try{
			log.info("调用了 "+jp.getTarget()+" 的 "+jp.getSignature().getName()
			+" 方法");
		}catch(Throwable e){
			log.error(jp.getSignature().getName()+" 方法发生异常: "+e);
			throw e;
		}finally{
			log.info(jp.getSignature().getName()+"方法执行结束");
		}
	}
}

解释:

1、@Aspect 将某个类定义为切面,使用@Before 将before() 方法定义为前置增强,使用@AfterReturning 将after()方法定义为后置增强。

2、为了获取当前连接点的信息,添加JoinPoint类型参数,Spring会自动注入该实例。

3、对于后置增强,还可以定义一个参数,用于接收目标方法的返回值,但要在@AfterReturning的returning属性指定参数名,Spring会自动将目标方法返回值赋值给指定名称参数



UserserviceLogger2.java:

package com.smbms.AopLog;

import java.util.Arrays;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class UserserviceLogger2 {
	private static final Logger log = Logger.getLogger(UserserviceLogger.class);
	
	@Pointcut("execution(* com.smbms.pojo..*.*(..))")
	public void pointcut(){}
	
	//前置增强方法
	@Before("pointcut()")
	public void before (JoinPoint jp) throws Throwable{
		log.info("***UserserviceLogger2*********before:调用了"+jp.getTarget()+" 的"+jp.getSignature().getName()
				+" 方法。方法入参:"+Arrays.toString(jp.getArgs()));
		try{
			log.info("调用了 "+jp.getTarget()+" 的 "+jp.getSignature().getName()
			+" 方法。");
		}catch(Throwable e){
			log.error(jp.getSignature().getName()+" 方法发生异常: "+e);
			throw e;
		}finally{
			log.info(jp.getSignature().getName()+"方法执行结束");
		}
	}
	
	@AfterReturning(pointcut = "pointcut()",returning = "result")
	//后置增强方法
	public void after (JoinPoint jp,Object result) throws Throwable{
		log.info("***UserserviceLogger2***********after:调用了 "+jp.getTarget()+" 的"+jp.getSignature().getName()
				+" 方法。方法入参:"+Arrays.toString(jp.getArgs())+result);
		try{
			log.info("调用了 "+jp.getTarget()+" 的 "+jp.getSignature().getName()
			+" 方法");
		}catch(Throwable e){
			log.error(jp.getSignature().getName()+" 方法发生异常: "+e);
			throw e;
		}finally{
			log.info(jp.getSignature().getName()+"方法执行结束");
		}
	}
}


解释:

1、@Before和@AfterReturning注解分别指定各自切入点为 com.smbms.pojo.. 包下面的所有类所有方法,对于所有相同的切入点,其实可以统一定义,以便于维护重用。

2、如上所示,@Pointcut 定义切入点表达式,切入点签名通过一个普通方法表示。



【2】使用了注解,配置文件就会变得简单了,在 applicationContext-mybatis.xml 添加以下内容:



	
	
	
	
	
	
		
	
	
	    
    
    
    
    
	
		
	
		
	
	    
	    	
	    		classpath:com/smbms/pojo/**/*.xml
	    	
	    
    
    
    
   	
   		
   	
   	
   	
   		
   	
	
   	
   	
   		
   	

    
   	
   	   	
    
    
     

【3】其他的bean和接口和实现类省略,重在aop的使用。


【4】输出结果:

INFO  12-31 12:11:22,713 ***UserserviceLogger*********before:璋冪敤浜哻om.smbms.pojo.UserServiceImpl@35841320 鐨刦indUsersWithConditions 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371]  (UserserviceLogger.java:17) 
INFO  12-31 12:11:22,713 璋冪敤浜? com.smbms.pojo.UserServiceImpl@35841320 鐨? findUsersWithConditions 鏂规硶銆?  (UserserviceLogger.java:20) 
INFO  12-31 12:11:22,714 findUsersWithConditions鏂规硶鎵ц缁撴潫  (UserserviceLogger.java:26) 
DEBUG 12-31 12:11:22,714 Returning cached instance of singleton bean 'com.smbms.AopLog.UserserviceLogger2#0'  (AbstractBeanFactory.java:247) 
INFO  12-31 12:11:22,715 ***UserserviceLogger2*********before:璋冪敤浜哻om.smbms.pojo.UserServiceImpl@35841320 鐨刦indUsersWithConditions 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371]  (UserserviceLogger2.java:22) 
INFO  12-31 12:11:22,715 璋冪敤浜? com.smbms.pojo.UserServiceImpl@35841320 鐨? findUsersWithConditions 鏂规硶銆?  (UserserviceLogger2.java:25) 
INFO  12-31 12:11:22,715 findUsersWithConditions鏂规硶鎵ц缁撴潫  (UserserviceLogger2.java:31) 
INFO  12-31 12:11:22,716 ***UserserviceLogger*********before:璋冪敤浜哻om.smbms.pojo.UserMapperImpl@19932c16 鐨刧etUserList 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371]  (UserserviceLogger.java:17) 
INFO  12-31 12:11:22,716 璋冪敤浜? com.smbms.pojo.UserMapperImpl@19932c16 鐨? getUserList 鏂规硶銆?  (UserserviceLogger.java:20) 
INFO  12-31 12:11:22,717 getUserList鏂规硶鎵ц缁撴潫  (UserserviceLogger.java:26) 
INFO  12-31 12:11:22,717 ***UserserviceLogger2*********before:璋冪敤浜哻om.smbms.pojo.UserMapperImpl@19932c16 鐨刧etUserList 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371]  (UserserviceLogger2.java:22) 
INFO  12-31 12:11:22,717 璋冪敤浜? com.smbms.pojo.UserMapperImpl@19932c16 鐨? getUserList 鏂规硶銆?  (UserserviceLogger2.java:25) 
INFO  12-31 12:11:22,718 getUserList鏂规硶鎵ц缁撴潫  (UserserviceLogger2.java:31) 
DEBUG 12-31 12:11:22,723 Creating a new SqlSession  (JakartaCommonsLoggingImpl.java:54) 
DEBUG 12-31 12:11:22,769 SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69c81773] was not registered for synchronization because synchronization is not active  (JakartaCommonsLoggingImpl.java:54) 
DEBUG 12-31 12:11:22,821 Fetching JDBC Connection from DataSource  (DataSourceUtils.java:110) 
DEBUG 12-31 12:11:25,399 JDBC Connection [jdbc:mysql://127.0.0.1:3306/test?
				useUnicode=true&characterEncoding=utf-8, UserName=root@localhost, MySQL Connector Java] will not be managed by Spring  (JakartaCommonsLoggingImpl.java:54) 
DEBUG 12-31 12:11:25,407 ==>  Preparing: select u.* ,r.roleName from smbms_user u ,smbms_role r where u.userName like CONCAT('%',?,'%') and u.userRole = ? and u.userRole = r.id   (JakartaCommonsLoggingImpl.java:54) 
DEBUG 12-31 12:11:25,479 ==> Parameters: mmb(String), 110(Integer)  (JakartaCommonsLoggingImpl.java:54) 
DEBUG 12-31 12:11:26,042 <==    Columns: id, userCode, userName, userPassword, gender, birthday, phone, address, userRole, createBy, createDate, modifyBy, modifyDate, roleName  (JakartaCommonsLoggingImpl.java:59) 
DEBUG 12-31 12:11:26,045 <==        Row: 1, test01, mmb02, 9876543210, 2, 1991-12-29, 0000, maoming, 110, 1, 2017-12-17 10:50:04.0, null, null, guan_li_yuan  (JakartaCommonsLoggingImpl.java:59) 
DEBUG 12-31 12:11:26,061 <==        Row: 2, test01, mmb02, scua, 2, 1991-12-29, 0000, maoming, 110, 1, 2017-12-17 10:56:48.0, null, null, guan_li_yuan  (JakartaCommonsLoggingImpl.java:59) 
DEBUG 12-31 12:11:26,063 <==        Row: 3, test01, mmb02, scua, 2, 1991-12-29, 0000, maoming, 110, 1, 2017-12-17 10:58:46.0, null, null, guan_li_yuan  (JakartaCommonsLoggingImpl.java:59) 
DEBUG 12-31 12:11:26,064 <==        Row: 4, test01, mmb02, scua, 2, 1991-12-29, 0000, maoming, 110, 1, 2017-12-17 11:01:42.0, null, null, guan_li_yuan  (JakartaCommonsLoggingImpl.java:59) 
DEBUG 12-31 12:11:26,065 <==        Row: 5, test01, mmb02, scua, 2, 1991-12-29, 0000, maoming, 110, 1, 2017-12-17 11:03:05.0, null, null, guan_li_yuan  (JakartaCommonsLoggingImpl.java:59) 
DEBUG 12-31 12:11:26,066 <==      Total: 5  (JakartaCommonsLoggingImpl.java:54) 
DEBUG 12-31 12:11:26,081 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69c81773]  (JakartaCommonsLoggingImpl.java:54) 
DEBUG 12-31 12:11:26,081 Returning JDBC Connection to DataSource  (DataSourceUtils.java:327) 
INFO  12-31 12:11:26,082 ***UserserviceLogger2***********after:璋冪敤浜? com.smbms.pojo.UserMapperImpl@19932c16 鐨刧etUserList 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371][com.smbms.pojo.User@51a9ad5e, com.smbms.pojo.User@5f20155b, com.smbms.pojo.User@72ade7e3, com.smbms.pojo.User@239105a8, com.smbms.pojo.User@3fce8fd9]  (UserserviceLogger2.java:38) 
INFO  12-31 12:11:26,082 璋冪敤浜? com.smbms.pojo.UserMapperImpl@19932c16 鐨? getUserList 鏂规硶  (UserserviceLogger2.java:41) 
INFO  12-31 12:11:26,083 getUserList鏂规硶鎵ц缁撴潫  (UserserviceLogger2.java:47) 
INFO  12-31 12:11:26,083 ****UserserviceLogger**********after:璋冪敤浜? com.smbms.pojo.UserMapperImpl@19932c16 鐨刧etUserList 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371][com.smbms.pojo.User@51a9ad5e, com.smbms.pojo.User@5f20155b, com.smbms.pojo.User@72ade7e3, com.smbms.pojo.User@239105a8, com.smbms.pojo.User@3fce8fd9]  (UserserviceLogger.java:34) 
INFO  12-31 12:11:26,083 璋冪敤浜? com.smbms.pojo.UserMapperImpl@19932c16 鐨? getUserList 鏂规硶  (UserserviceLogger.java:37) 
INFO  12-31 12:11:26,083 getUserList鏂规硶鎵ц缁撴潫  (UserserviceLogger.java:43) 
INFO  12-31 12:11:26,084 ***UserserviceLogger2***********after:璋冪敤浜? com.smbms.pojo.UserServiceImpl@35841320 鐨刦indUsersWithConditions 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371][com.smbms.pojo.User@51a9ad5e, com.smbms.pojo.User@5f20155b, com.smbms.pojo.User@72ade7e3, com.smbms.pojo.User@239105a8, com.smbms.pojo.User@3fce8fd9]  (UserserviceLogger2.java:38) 
INFO  12-31 12:11:26,084 璋冪敤浜? com.smbms.pojo.UserServiceImpl@35841320 鐨? findUsersWithConditions 鏂规硶  (UserserviceLogger2.java:41) 
INFO  12-31 12:11:26,084 findUsersWithConditions鏂规硶鎵ц缁撴潫  (UserserviceLogger2.java:47) 
INFO  12-31 12:11:26,084 ****UserserviceLogger**********after:璋冪敤浜? com.smbms.pojo.UserServiceImpl@35841320 鐨刦indUsersWithConditions 鏂规硶銆傛柟娉曞叆鍙傦細[com.smbms.pojo.User@3cce5371][com.smbms.pojo.User@51a9ad5e, com.smbms.pojo.User@5f20155b, com.smbms.pojo.User@72ade7e3, com.smbms.pojo.User@239105a8, com.smbms.pojo.User@3fce8fd9]  (UserserviceLogger.java:34) 
INFO  12-31 12:11:26,084 璋冪敤浜? com.smbms.pojo.UserServiceImpl@35841320 鐨? findUsersWithConditions 鏂规硶  (UserserviceLogger.java:37) 
INFO  12-31 12:11:26,084 findUsersWithConditions鏂规硶鎵ц缁撴潫  (UserserviceLogger.java:43) 
testGetUserList userCode:test01userName: mmb02userRole: 110userRoleName: guan_li_yuanuserAddress: null
testGetUserList userCode:test01userName: mmb02userRole: 110userRoleName: guan_li_yuanuserAddress: null
testGetUserList userCode:test01userName: mmb02userRole: 110userRoleName: guan_li_yuanuserAddress: null
testGetUserList userCode:test01userName: mmb02userRole: 110userRoleName: guan_li_yuanuserAddress: null
testGetUserList userCode:test01userName: mmb02userRole: 110userRoleName: guan_li_yuanuserAddress: null

继续,下面是定义异常抛出增强:Spring(12):使用注解(@AfterThrowing/@After/@Around)实现AOP异常增强与实例;


你可能感兴趣的:(项目实战)