Java 注解是JDK5.0引入的一种注释机制,它可以用在类、方法、变量、参数上,注解是通过Java反射机制获取标注的内容,从而供指定的工具类或者框架使用。在用SpringBoot做项目开发时,我们用了很多的Spring框架的注解,如@Controller、@Service 等等,但对于一些特定的应用场景,我们可以通过自定义注解结合Spring的AOP技术实现一些功能。
下面自定义一个@PrintParam注解来实现,请求方法时,自动打印请求的参数,简单代码实现如下:
1.注解声明
用Java的元注解声明自定义注解的使用位置、保留的生命周期
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PrintParam { }
2.自定义注解切面环绕通知配置
此处要用到spring的AOP技术
@Pointcut注解解释 切入点,表达式配置的是匹配要执行的方法 动作关键字(访问修饰符 返回值 包.类/接口名.方法名(参数列表)异常名) 1.动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点 2.访问修饰符:public,private等,可以省略 3.返回值 4.包名 5.类/接口名 6.方法名 7.参数 8.异常名:方法定义中抛出异常,可以省略 其中 .. 表示任意多个等级 * 表示精准匹配 @Pointcut("execution(* com.demo.controller..*.*(..))") 表达式意思是 任意返回值 com.demo.controller 包以及所有子包 任意类 任意方法 (任意参数)
@Aspect @Component @Slf4j public class PrintParamAspect { @Pointcut("execution(* com.demo.controller..*.*(..))") public void printParam() { } @Around(value = "printParam()") public Object around(ProceedingJoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); PrintParam annotation = method.getAnnotation(PrintParam.class); if (annotation != null) { String methodName = method.getName(); log.info("方法:{}", methodName); Parameter[] parameters = method.getParameters(); Object[] args = joinPoint.getArgs(); for (int i = 0; i < parameters.length; i++) { log.info("参数名称:{},值:{}", parameters[i], args[i]); } } Object obj = null; try { obj = joinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } return obj; } }
3.请求方法应用注解
@RequestMapping("/findById") @PrintParam public User findById(@RequestParam(name = "id", required = false) Long id, @RequestParam(name = "name", required = false) String name) { return userService.findById(id); }
4.打印结果
14:16:39.010 [INFO ] [http-nio-9090-exec-5] [com.demo.aspect.PrintParamAspect] 方法:findById 14:16:39.010 [INFO ] [http-nio-9090-exec-5] [com.demo.aspect.PrintParamAspect] 参数名称:java.lang.Long id,值:1 14:16:39.010 [INFO ] [http-nio-9090-exec-5] [com.demo.aspect.PrintParamAspect] 参数名称:java.lang.String name,值:testName