Spring AOP

AOP是什么
AOP是面向切面编程的意思,全称为 Aspect Oriented Programming 。它是一种基于OOP之上的一种编程范式,可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态添加功能的一种技术。

AOP的编程思想就是把很多类对象中的横切问题点,从业务逻辑中分离出来,从而达到解耦的目的,增加代码的重用性,提高开发效率。

AOP应用场景
日志记录        异常处理        权限验证        缓存处理
事务处理        数据持久化     效率检查        内容分发

AOP 术语
连接点(joinpoint)(类中所有方法)程序执行过程中某个特定的位置,如方法的调用或特定的异常被抛出。连接点具体到类中的方法。
切入点(pointcut):(缺失共性功能代码的方法)每个类都拥有多个连接点,可以理解是连接点的集合。也就是指被抽取类中多个方法里的共性功能的方法。切入点一定是连接点,连接点不一定是切入点。
通知(advice):(被抽取的共性功能的代码逻辑)切入点对应的方法的共性功能被抽取后,组成独立代码逻辑,被封装在某个类的某个方法中,在被抽取了共性功能的方法被执行时,这些代码逻辑还要加入原始方法的执行,这些被抽取出来组成独立代码逻辑的共性功能成为通知。
       通知的种类
前置通知(Bofore advice):即在目标方法调用之前执行。注意:即无论方法是否遇到异常都执行。
后置通知(After returning advice):在目标方法执行后执行,前提是目标方法没有遇到异常,如果有异常则不执行通知。
异常通知(After throwing advice):在目标方法抛出异常时执行,可以获取异常信息。
最终通知(After finally advice):在目标方法执行后执行,无论是否是异常执行。
环绕通知(Around advice):环绕通知,最强大的通知类型,可以控制目标方法的执行,可以在目标执行全过程中进行执行。
引入(Introduction): 添加方法或字段到被通知的类。通知只能抽取逻辑代码,变量是拿不出来的,把变量引入到切入点方法中去,就要用引入。
目标对象(target):指包含切入点的类对象,通知织入的目标类。
AOP代理(aop Proxy):也叫代理对象,代理目标对象。 AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
织入(weaving):将增强添加到目标类的具体连接点的过程,通过AOP代理,将通知加入到切入点对应位置的动作。
切面(aspect):切面由切入点和通知组成,既包括横切逻辑的定义也包括连接点的定义。

Spring AOP 底层实现:是通过JDK动态代理或CGLib代理在运行时期在对象初始化阶段织入代码的。
JDK动态代理基于接口实现
CGLib是基于类的继承实现

实现步骤:
1.定义一个切面类Aspect
即在声明的类,增加@Component @Aspect两个注解,SpringBoot中要引入spring-boot-start-aop依赖包
2.定义切点Pointcut
定义切点,并定义切点在那些地方执行,采用@Pointcut注解完成,如@Pointcut(public * com.xxx.xxx.*.*(..))
规则:修饰符(可以不写,但不能用*) + 返回类型 + 那些包下的类 + 那些方法 + 方法参数
        "*"代表返回类型不限   ".."两个点代表参数不限
3.定义Advice通知
利用通知的5种类型注解@Before、@After、@AfterReturn、@AfterThrowing、@Around来完成在某些切点的增强动作,如@Before("myPointcut()"),myPointcut为第二步骤定义的切点

@Before: 标识一个前置增强方法,相当于BeforeAdvice的功能.
@After: final增强,不管是抛出异常或者正常退出都会执行.
@AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行.
@AfterThrowing: 异常抛出增强,相当于ThrowsAdvice.
@Around: 环绕增强,相当于MethodInterceptor.
execution:用于匹配方法执行的连接点;

引入依赖包

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.5.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.5.3</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.5.3</version>
        </dependency>
    </dependencies>

controller层

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(@RequestParam("name") String name){
        return "hello" +name;
    }
}
@Aspect
@Component
public class MyAdvice {
    private Logger logger = LoggerFactory.getLogger(MyAdvice.class);

    //定义切面
    @Pointcut(value = "execution( * spring.aop.controller.*.*(..))")
    public void myPointcut(){

    }

    //环绕通知
    @Around("myPointcut()")
    public Object myLogger(ProceedingJoinPoint pjp) throws Throwable {
        //获取增强了哪些类的名字
        String className = pjp.getTarget().getClass().toString();
        //获取方法名
        String methoName = pjp.getSignature().getName();
        //获取参数
        Object[] array = pjp.getArgs();

        ObjectMapper mapper = new ObjectMapper();

        logger.info("调用前:"+className+":"+methoName+"传递的参数:"+mapper.writeValueAsString(array));

        Object obj = pjp.proceed();

        logger.info("调用后:"+className+":"+methoName+"返回值:"+mapper.writeValueAsString(obj));

        return obj;
    }

    @Before("myPointcut()")
    public void before(){
        System.out.println("前置通知");
    }

    @After("myPointcut()")
    public void after(){
        System.out.println("后置通知");
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值