日志--切面(AOP)的使用,以及配合使用自定义注解
原材料:两个jar包,使用注解进行配置
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.12</version> </dependency>
1.在spring的xml当中进行配置切面自动代理
<!--定义切面 自动代理-->
<aop:aspectj-autoproxy/>
2.编写切面的类
1 2 3 4 5 6 import org.aspectj.lang.JoinPoint; 7 import org.aspectj.lang.annotation.After; 8 import org.aspectj.lang.annotation.Aspect; 9 import org.aspectj.lang.annotation.Before; 10 import org.aspectj.lang.annotation.Pointcut; 11 import org.aspectj.lang.reflect.MethodSignature; 12 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.stereotype.Component; 14 15 import java.lang.reflect.Method; 16 17 /** 18 * 切面 用于日志记录的功能 19 * 20 */ 21 @Aspect 22 @Component 23 public class FlowLoggerImpl extends FlowLogger { 24 25 @Autowired 26 private SpareService spareService; 27 /** 28 * 在流程当中修改备品备件 29 */
30 @Pointcut("execution(* com.ztesoft.resmaster.module.spare.service.SpareService.setSpareArchive(..))" + 31 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.setSpareRollBack(..))"+ 32 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.changeOperateOp(..))"+ 33 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.ClearOrderId(..))"+ 34 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.delSpareByOrder(..))"+ 35 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.rollBackSpares(..))"+ 36 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.setSpareState(..))"+ 37 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.delInventoryAndSpare(..))"+ 38 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.updateSpareInfo(..))"+ 39 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.updateSpareInfoNotStr(..))"+ 40 "||execution(* com.ztesoft.resmaster.module.spare.service.SpareService.modifySpareInfo(..))"+ 41 "&&@annotation(com.ztesoft.resmaster.module.spare.log.domain.AspectLog)")
//注明所要切面的方法,并且是有AspectLog该注解才可执行切面 42 @Override 43 public void edit() { 44 45 } 46 47 @Pointcut("execution(* com.ztesoft.resmaster.module.spare.service.SpareService.createSpareBatch(..))" + 48 "&&@annotation(com.ztesoft.resmaster.module.spare.log.domain.AspectLog)") 49 @Override 50 public void add() { 51 52 } 53 54 @After("add()")//使用执行后执行 55 public void afterAdd(JoinPoint joinPoint){ 56 getParamAndLog(joinPoint); 57 } 58 59 @Before("edit()")//执行前执行 60 public void beforeFlowEdit(JoinPoint joinPoint){ 61 getParamAndLog(joinPoint); 62 } 63 /** 64 * 文件操作 65 */ 66 @Override 67 public void fileOperation() { 68 69 } 70 71 private void getParamAndLog(JoinPoint joinPoint){ 72 Object [] parm = joinPoint.getArgs();//获得切面方法当中的参数 73 MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();//获得切面当中方法签名 74 Method method = methodSignature.getMethod();//获得签名方法 75 AspectLog aspectLog = method.getAnnotation(AspectLog.class);//获得在方法上面的注解 76 String resObjectId = ""; 77 String orderId = ""; 78 if (AspectLog.AspectEnum.ASPECT_ENUM_RES_OBJECT_ID.equals(aspectLog.key())) { 79 resObjectId = String.valueOf(parm[Integer.valueOf(aspectLog.value())]);//获得需要的值 80 } else if (AspectLog.AspectEnum.ASPECT_ENUM_ORDER_ID.equals(aspectLog.key())) { 81 orderId = String.valueOf(parm[Integer.valueOf(aspectLog.value())]); 82 }else if (AspectLog.AspectEnum.ASPECT_ENUM_RES_ID_AND_ORDER_ID.equals(aspectLog.key())) { 83 String [] positon = aspectLog.value().split(","); 84 resObjectId = String.valueOf(parm[Integer.valueOf(positon[0])]); 85 orderId = String.valueOf(parm[Integer.valueOf(positon[1])]); 86 } 87 //日志记录 88 spareService.spareLog(resObjectId,orderId); 89 } 90 }
3.自定义注解
1
2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 /** 9 * 10 * 该方法用于标注日志操作的地方 11 */ 12 @Target(ElementType.METHOD)//定义成在方法上面的注解 13 @Retention(RetentionPolicy.RUNTIME)//运行时执行 14 public @interface AspectLog { 15 /** 16 * 通过这个注解表示的是 注释方法当中的参数,第几个个参数值是是resObjectId 17 * 通过枚举来进行标记,默认第一个为 res_object_id 18 * 0,1,2,3,4,5 19 * @return 20 */
21 AspectEnum key() default AspectEnum.ASPECT_ENUM_RES_OBJECT_ID; 22 String value() default ""; 23 public enum AspectEnum{//定义参数枚举 24 /** 25 * RES_OBJECT_ID的位置 26 */ 27 ASPECT_ENUM_RES_OBJECT_ID, 28 /** 29 * ORDER_ID的位置 30 */ 31 ASPECT_ENUM_ORDER_ID, 32 /** 33 * 两个共同的位置 默认第一个为 res_object_id的位置 34 */ 35 ASPECT_ENUM_RES_ID_AND_ORDER_ID; 36 } 37 }
3.在方法上面进行注解 因为在获得方法参数的时候,大部分切面的方法都是String,String,String这样的入参方式,无法判断出想要的到的是哪个参数,所以需要使用注解的方式来获得参数,使用AOP仅仅支持在方法上面的注解,不支持参数注解。
第几个是想要的参数,最后来进行处理
1 @AspectLog(key = AspectLog.AspectEnum.ASPECT_ENUM_RES_OBJECT_ID,value ="0" ) 2 public int updateSpareInfo(String resObjectId, String values, String column) { 3 int result = spareDao.updateSpareInfo(resObjectId, values, column); 4 return result; 5 }