2017/12/31
AspectJ,一个面向切面的框架。@AspectJ 是AspectJ版本5的新增功能,所以确保JDK是5.0以上版本,负责无法使用注解技术。
(1)Spring通过集成AspectJ实现了以注解定义切面,大大减少了配置文件的工作量。
(2)java的反射机制无法获取方法参数名,Spring还利用了字节码处理框架asm处理@AspectJ描述的方法参数名。
下面通过一个实例演示:
【0】文件结构和jar包
图1
图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
【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异常增强与实例;