SpringAOP切入点规范及获取方法参数的实现
切入点规范
@Pointcut("execution(* com.example.server.service.TeacherService.*(..))")
上面的切入点会切入com.example.server.service.TeacherService下面的所有方法。
下面来详细介绍一下切入点表达式的规范。
1、execution():表达式主体。
2、第一个位置:表示返回类型, *号表示所有的类型。
3、第二个位置:表示需要拦截的包名.类名.方法名(方法参数)。
需要注意的是必须是全类名。其中可以使用*表示所有包。
比如说:com.example.server.service.表示service包下的所有类;com.example.server..则表示server包下的所有包及其所有类。
可以具体指定某一个方法,也可以用表示该类的所有方法(满足之前的返回类型)
同样,参数可以是具体的,例如:(int, String),也可以用(..)来表示任意参数。(只有参数匹配的方法才能被切入)
AOP中获取方法参数
"execution(* com.example.server.service.TeacherService.uploadExperience(..)) && args(userId)"
大家可以看到,在以上表达式的基础上添加了一点改动,这样我们就能在AOP中获取到切入方法调用时的参数,这样我们就能在AOP方法中使用这个参数。
以下是一个示例:
@After("execution(* com.example.server.service.TeacherService.uploadExperience(..)) && args(userId)") public void updateLevel(Long userId){ //代码块,现在就可以在代码块中使用userId }
AOP获取session的参数
有时需要在AOP中使用到之前存储在session中的值。其实这也非常简单。
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpSession session = attr.getRequest().getSession(true); long userId = (long) session.getAttribute(USER_ID);
同理,我们通过ServletRequestAttributes也可以获取到request和response
HttpServletResponse response = attr.getResponse(); HttpServletRequest request = attr.getRequest();
SpringAOP:获取切入点注释的参数
spring aop如何在切面类中获取切入点相关方法的参数、方法名、返回值、异常等信息
aop思想可以很好的帮助我们实现代码的解耦,比如我们之前提到的,将日志代码与业务层代码完全独立,通过spring aop的代理类进行整合。在切面类中,我们也能够通过spring提供的接口,很好的获取原切入点的相关信息。
首先,我们还是从代码着手
业务层代码StudentServiceImpl
@Service("studentService") public class StudentServiceImpl implements StudentService { @Override public int addStudent(Student student) throws Exception { System.out.println("addStudent...业务层代码执行..."); return 1; } @Override public int deleteStudent(Integer id) throws Exception{ System.out.println("deleteStudent...业务层代码执行..."); int i = 1/0; return 0; } }
切面类StudentServiceLogger
@Aspect @Component public class StudentServiceLogger { @Before("execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )") public void doBefore(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); String methodName = joinPoint.getSignature().getName(); System.out.println(methodName+"方法执行前..."); System.out.println("参数为:"+ Arrays.asList(args)); } @After("execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )") public void doAfter(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); System.out.println(methodName+"方法执行后..."); } @AfterReturning(value = "execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )" , returning = "returning") public void doReturn(JoinPoint joinPoint,Object returning){ String methodName = joinPoint.getSignature().getName(); System.out.println(methodName+"方法返回,返回值为:"+returning); } @AfterThrowing(value = "execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )",throwing = "ex") public void doThrow(JoinPoint joinPoint,Exception ex){ String methodName = joinPoint.getSignature().getName(); System.out.println(methodName+"方法异常,异常信息为:"+ex.getMessage()); } }
测试类AopTest
public class AopTest { ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); @Test public void test1() throws Exception { StudentService studentService = ac.getBean("studentService",StudentService.class); studentService.addStudent(new Student()); System.out.println("==================割==============="); studentService.deleteStudent(1); } }
最后是日志输出结果
addStudent方法执行前...
参数为:[com.wuwl.domain.Student@7e5c856f]
addStudent...业务层代码执行...
addStudent方法执行后...
addStudent方法返回,返回值为:1
==================割===============
deleteStudent方法执行前...
参数为:[1]
deleteStudent...业务层代码执行...
deleteStudent方法执行后...
deleteStudent方法异常,异常信息为:/ by zero
关于切入点方法的相关信息,spring很好的封装在了org.aspectj.lang.JoinPoint接口中,这里需要注意的是,在org.aopalliance.intercept包下,也有这样命名的一个接口,千万不要搞错了。
joinPoint.getArgs()方法可以返回切入方法的参数信息,返回值为一个数组,遍历即可获取;joinPoint.getSignature()方法的返回值为方法签名,签名接口中就包括方法名之类的信息。
如果需要在通知方法中获取切入方法的返回值,或者异常信息,则需要使用到对应注解的对应属性才行。
点开@AfterReturning注解可以看到一个String returning() default "";属性,在通知方法中添加返回值参数,然后再注解中声明该参数为切入方法的返回值即可,操作方法可参考上面的代码。
同理可以,使用@AfterThrowing注解的String throwing() default "";属性,可以获取到切入方法抛出的异常信息。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。