上篇我们学习了《SpringBoot实战14-Spring基础-Spring EL表达式》,本篇我们学习面向切面编程AOP。
7 AOP
面向切面编程(Aspect-Oriented Programming简称AOP),它可以做到添加额外的行为到现有的指定条件的一批Bean上,但是我们并不需要修改Bean的代码,这样使得额外行为和Bean本身行为关注隔离。
学习AOP,我们首先要熟悉下面的概念:
切面:Aspect,编写额外行为的地方;连接点:Join Point,被拦截的方法;切点:PointCut,通过条件匹配一批连接点;建言:Advice,对于每个连接点需要做的行为;目标对象:符合指定条件的Bean
我们使用AOP开发需要使用@EnableAspectJAutoProxy注解来开启AspectJ的支持,Spring Boot已经为我们自动做了配置,我们无需额外声明。
我们来编写一个使用AOP来记录操作日志的例子,我们先编写一个注解用来给切点作为拦截条件:
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Logging { String value() default "";}
目标对象为:
@Servicepublic class PersonService { @Logging("人员新增操作") public void add(String name){ //每个被拦截的方法都是连接点 System.out.println("人员新增"); } @Logging("人员删除操作") public void remove(String name){ System.out.println("人员删除"); } @Logging("人员查询操作") public String query(String name){ System.out.println("人员查询"); return name; } @Logging("人员修改操作") public String modify(String name){ System.out.println("人员修改"); return name.toUpperCase(); }}
下面是我们最重要的部分,切面部分的编写:
@Aspect //1@Componentpublic class LoggingAspect { @Pointcut("@annotation(top.wisely.springfundamentals.aop.Logging)") //2 public void annotationPointCut(){} @Before("annotationPointCut()") //3 public void beforeAnnotationPointCut(JoinPoint joinPoint){//4 String name = (String) joinPoint.getArgs()[0]; //5 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); String action = methodSignature.getMethod().getAnnotation(Logging.class).value(); //6 System.out.println("对" + name + "进行了"+ action); } @AfterReturning(pointcut = "annotationPointCut()", returning = "retName") //7 public void afterReturningAnnotationPointCut(JoinPoint joinPoint, String retName){ String name = (String) joinPoint.getArgs()[0]; MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); String action = methodSignature.getMethod().getAnnotation(Logging.class).value(); System.out.println("对" + name + "进行了"+ action + ",返回的名字为:" + retName); } }
使用@Aspect定义一个切面;使用@Pointcut,他将所有注解了@Logging注解的方法作为条件;使用@Before建言,它使用的切点annotationPointCut(),针对符合切点条件的Bean执行beforeAnnotationPointCut()方法里的行为;JoinPoint joinPoint代表被拦截的方法,可以从joinPoint获得方法的签名信息;通过joinPoint获得被拦截方法的参数;通过jointPoint获得被拦截方法的注解信息;使用@AfterReturning建言,我们可以获得被拦截方法的返回值retName。
我们在JavaConfig执行:
@BeanCommandLineRunner aopCle(PersonService personService){ return args -> { personService.add("wyf"); personService.remove("wyf"); personService.query("wyf"); personService.modify("wyf"); };}
下一篇《SpringBoot实战16-Spring基础-Spring注解的工作原理》