import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import java.io.PrintStream; import java.util.Arrays; /** * @Author : guoyanan * @Title : 配置切面类,用于记录系统日志 * @Time : 2019/03/15 15:29 * @Document : */ @Aspect @Component public class SystemLogs { /** * 配置切点方法 * 方便统一管理切点 * execution属性为切点需要管理的包路径 * 规则: * execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?) * 规则解释: * modifiers-pattern?:修饰符匹配,也就是关键字匹配例如:public、private、protect;*代表所有 * ret-type-pattern:返回值匹配,可以是java基础类型也可以是自义定类,例如:基础类:String、List等,自定义类:UserInfo、OrderInfo等 * eclaring-type-pattern?:类路径匹配,切面需要管理的包路径,可以精确到类。也可以包下所有类,例如:com.test.* * name-pattern:方法名匹配,根据方法名建立切点,例如:setName、set*等;set*表示所有以set开头的方法 * param-pattern:参数名匹配,根据方法的参数类型建立切点,参数使用“,”隔开使用*标识参数可以是任意类型,如果是(..)说明不限制参数个数 * throws-pattern?:异常类型匹配,可以根据异常类型匹配切点。例如:NullPointException、IOException等 * 注意: * 带有?的说明是可以省略的类型 * 举例: * execution(public String com.config.SystemTest.HelloWord(String)) IOException * 这个语句的含义:匹配com.config.路径下SystemTest类中方法名为HelloWord且参数为一个String类型返回类型也是String的IOException异常的一个切点。 * 测试throws-pattern?:加与不加,没有明显的异常。可以认为是不需要的规则。 */ @Pointcut("execution(public String com.busi.config.SystemTest.HelloWord(String)) IOException") public void HelloWord(){} /** * 引用切点HelloWord * 打印切点进入前的参数和访问的类 * 访问切点前执行方法 * @param point */ @Before("HelloWord()") private void before(JoinPoint point){ System.out.println("@Before:模拟权限检查..."); System.out.println("@Before:目标方法为:" + point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName()); System.out.println("@Before:参数为:" + Arrays.toString(point.getArgs())); System.out.println("@Before:被织入的目标对象为:" + point.getTarget()); } /** * 访问切点执行后运行此方法 * @param point * @param returnValue */ @AfterReturning(pointcut="HelloWord()",returning="returnValue") private void afterReturning(JoinPoint point,Object returnValue){ System.out.println("@AfterReturning:模拟日志记录功能..."); System.out.println("@AfterReturning:目标方法为:" + point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName()); System.out.println("@AfterReturning:参数为:" + Arrays.toString(point.getArgs())); System.out.println("@AfterReturning:返回值为:" + returnValue); System.out.println("@AfterReturning:被织入的目标对象为:" + point.getTarget()); } /** * 访问切点方法后运行方法,与@AfterReturning的区别是缺少了returning属性 * 认为:@AfterReturning是@After的升级 * @param point */ @After("HelloWord()") public void after(JoinPoint point) { System.out.println("@After:模拟释放资源..."); System.out.println("@After:目标方法为:" + point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName()); System.out.println("@After:参数为:" + Arrays.toString(point.getArgs())); System.out.println("@After:被织入的目标对象为:" + point.getTarget()); } /** * 执行后发生异常方法,可以用于捕捉执行过程中的异常 * @param jp * @param e */ @AfterThrowing(pointcut = "HelloWord()",throwing="e") public void doException(JoinPoint jp,Throwable e){ if(e!=null){ PrintStream printStream=System.err; printStream.println(); } } }
切点方法:
/** * @Author : guoyanan * @Title : 切点测试方法 * @Time : 2019/03/15 15:22 * @Document : */ @RestController public class SystemTest { @RequestMapping("/hello") public String HelloWord(@RequestParam("na") String name)throws NullPointerException{ String str = null; try { str.toUpperCase(); }catch (NullPointerException e){ } return "Hello Word"+name; } @RequestMapping("/word") public String Word(@RequestParam("na") String name){ String str = null; str.toUpperCase(); return "Word"+name; } }
执行结果打印:
@Before:模拟权限检查...
@Before:目标方法为:com.busi.config.SystemTest.HelloWord
@Before:参数为:[1]
@Before:被织入的目标对象为:com.busi.config.SystemTest@17933314
@After:模拟释放资源...
@After:目标方法为:com.busi.config.SystemTest.HelloWord
@After:参数为:[1]
@After:被织入的目标对象为:com.busi.config.SystemTest@17933314
@AfterReturning:模拟日志记录功能...
@AfterReturning:目标方法为:com.busi.config.SystemTest.HelloWord
@AfterReturning:参数为:[1]
@AfterReturning:返回值为:Hello Word1
@AfterReturning:被织入的目标对象为:com.busi.config.SystemTest@17933314