Spring AOP注解案例及基本原理详解
切面:Aspect
切面=切入点+通知。在老的spring版本中通常用xml配置,现在通常是一个类带上@Aspect注解。切面负责将横切逻辑(通知)编织到指定的连接点中。
目标对象:Target
将要被增强的对象。
连接点:JoinPoint
可以被拦截到的程序执行点,在spring中就是类中的方法。
切入点:PointCut
需要执行拦截的方法,也就是具体实施了横切逻辑的方法。切入点的规则在spring中通过AspectJpointcutexpressionlanguage来描述。
切入点与连接点的区别:连接点是所有可以被"切"的点;切入点是真正要切的点。
通知:Advice
针对切入点的横切逻辑,包含“around”、“before”和“after”等不同类型的通知。
通知的作用点如其命名:
- before:在切入点之前执行
- after:在切入点之后执行
- around:在切入点拦截方法,自定义前后,更灵活
还有一些异常处理的通知,这里不一一举例
织入:Weaving
将切面和目标对象连接起来,创建代理对象的过程。spring中用的是动态代理。假如目标对象有接口,使用jdk动态代理;否则使用cglib动态代理。
说了这么多概念,看看代码实现可能会使读者理解的更深刻一些,这里简单写一个通过注解增强方法的AOP-Demo。
首先是切面类:
packagecom.example.demo.aop;
importorg.aspectj.lang.JoinPoint;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.aspectj.lang.annotation.*;
importorg.springframework.stereotype.Component;
/**
*@authorFcb
*@date2020/6/20
*@description切面类=切入点+通知
*/
@Aspect
@Component
publicclassLogAspect{
//这个方法定义了切入点
@Pointcut("@annotation(com.example.demo.aop.anno.MyLog)")
publicvoidpointCut(){}
//这个方法定义了具体的通知
@After("pointCut()")
publicvoidrecordRequestParam(JoinPointjoinPoint){
for(Objects:joinPoint.getArgs()){
//打印所有参数,实际中就是记录日志了
System.out.println("afteradvice:"+s);
}
}
//这个方法定义了具体的通知
@Before("pointCut()")
publicvoidstartRecord(JoinPointjoinPoint){
for(Objects:joinPoint.getArgs()){
//打印所有参数
System.out.println("beforeadvice:"+s);
}
}
//这个方法定义了具体的通知
@Around("pointCut()")
publicObjectaroundRecord(ProceedingJoinPointpjp)throwsThrowable{
for(Objects:pjp.getArgs()){
//打印所有参数
System.out.println("aroundadvice:"+s);
}
returnpjp.proceed();
}
}
注解:
packagecom.example.demo.aop.anno;
importjava.lang.annotation.*;
/**
*@authorFcb
*@date2020/6/20
*@description
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public@interfaceMyLog{
}
目标类:
packagecom.example.demo.aop.target;
importcom.example.demo.aop.anno.MyLog;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importorg.springframework.web.bind.annotation.RestController;
/**
*@authorFcb
*@date2020/6/20
*@description
*/
@RestController
publicclassMockController{
@RequestMapping("/hello")
@MyLog
publicStringhelloAop(@RequestParamStringkey){
System.out.println("dosomething...");
return"helloworld";
}
}
最后是测试类:
packagecom.example.demo.aop.target;
importorg.junit.jupiter.api.Test;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;
/**
*@authorFcb
*@date2020/6/20
*@description
*/
@SpringBootTest
classMockControllerTest{
@Autowired
MockControllermockController;
@Test
voidhelloAop(){
mockController.helloAop("aop");
}
}
控制台结果:
aroundadvice:aop
beforeadvice:aop
dosomething...
afteradvice:aop
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。