在上一节中,讲到了三个注解@Around @Before @After,通过这些操作可以在方法执行前后执行某些操作。如果我们有个方法想实现aop,根据我们上节所讲的,要先找到切入点,然后再对这个切入点进行前后操作。从上面的逻辑可以看出,我们每次想要方法实现aop就要都要做一些重复的操作,大大影响力代码的简洁和可读性。
首先我们设想一下有没有一种方法,只要我们在想要实现aop的方法上面加个标记就能实现aop的功能。是的大家可能想到了,这个标记就是注解。
原始切面定义:
@Aspect
@Component
public class AopServiceImpl {
@Pointcut("execution(* com.aop.aop.controller..*(..))")
public void record(){
System.out.println("hahahha");
}
@Before("record()")
public void before(){
System.out.println("before................");
}
}
从代码可以看出,切点指向的是个范围,在此范围内所有的方法都实现了Aop,在实际开发中我们可能只需要某各类中的某个方法实现aop,因此我们可以将切点Pointcut精确到某个方法
@Pointcut("execution(* com.aop.aop.controller.SysController.sayHello())")
public void record(){
System.out.println("hahahha");
}
@Before("record()")
public void before(){
System.out.println("before................");
}
一个方法还好只需定义一次,如果多个方法需要使用同一个advice,就要声明多个切点,显然这种方法会造成大量重复代码影响代码可读性。为了解决此类问题我们引入@annotation()
我们先定义一个注解:
@Target({ElementType.METHOD}) //声明注解作用在方法上面
@Retention(RetentionPolicy.RUNTIME) //注解保留至运行时
public @interface AopInter {
}
改良后的advice
@Aspect
@Component
public class NewAopSerivceImpl {
@Before("@annotation(com.aop.aop.AopInter)") //该advice作用在有@AopInter注解的方法下面
public void before(){
System.out.println("before................");
}
}
测试执行sayHello,与syGoodBye
@Controller
public class SysController {
@GetMapping("/sayHello")
@ResponseBody
public String sayHello(){
System.out.println("执行结果................hello");
return "hello";
}
@GetMapping("/syGoodBye")
@AopInter
public String syGoodBye(){
System.out.println("执行结果................goodBye");
return "goodBye";
}
}
结果
执行结果................hello
before................
执行结果................goodBye
可以看出syGoodBye使用该adivce,sayHello并没有使用。因此如果有方法想使用该adivce只需加上@AopInter注解即可。