SpringAop (一、AOP基础概述以及示例)

本文深入解析面向切面编程(AOP)的概念与原理,探讨其在参数匹配、安全控制、日志记录等方面的应用,并通过Spring框架的示例代码,展示如何使用AOP解决重复代码问题,提高代码复用性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说过IOC,就接着说一下AOP吧。AOP是个啥?IOC是控制反转,将Bean的初始化交给Spring容器,然后通过DI依赖注入到程序中,那AOP是干嘛的?它有没有什么类似DI的方法?

AOP

AOP 是 Aspect Oriented Programming 的缩写,翻译为:面向切面编程

所以切面是什么意思?理解了切面,我们才是真正的理解了AOP。

在实现业务的时候,每个接口都会做用户是否被禁用校验,这段代码很简单,可能也就是两行代码,但是每个方法都写一遍也太麻烦了。

  • 想法一:抽出一个公共方法,在每次调用接口时调用一下。是,简单了一点,但是觉得还是麻烦。
  • 想法二:在拦截器里面做?等等。。过滤器,拦截器,aop。怎么感觉都差不多?三者区别?以后再说。不在过滤器,拦截器里面做处理的原因是涉及到业务逻辑,前二者粒度太粗了,都是从request里面获取数据操作。
  • 想法三:利用AOP实现。

所以AOP可以帮助我们干啥?

  • 参数匹配和校验
  • 安全控制
  • 日志记录
  • 埋点
  • 性能处理
  • 等…

AOP术语

刚才说道AOP里面有个关键词叫:切面,其实不止有切面,还有好多关键词。。

  1. 连接点(Joinpoint):在程序执行过程中某个特定的点,比如类开始初始化前、类初始化后、类的某个方法调用前/后。在Spring AOP中,一个连接点总是表示一个方法的执行。
  2. 切点(Pointcut):每个类中都有多个连接点,AOP通过"切点"定个位特性的连接点。一个切点可以匹配多个连接点。
  3. 增强 - 通知(Advice):增强是织入目标连接点上的一段程序代码。同时还拥有另一个和连接点相关的信息,是执行点的方位。
  4. 目标对象(Target):目标对象就是我们需要对它进行增强的业务类~
  5. 织入(Weaving):织入就是将增强添加到目标类具体连接点上的过程。
  6. 代理(Proxy):一个类被AOP织入增强后,就产生了一个结果类,他是融合了原类和增强逻辑的代理类。
  7. 切面(Aspect):切面由切点和增强(或引介)组成,或者只由增强(或引介)实现。

AOP示例

package com.study.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;

@Aspect
@Configuration
public class TestAop {

    final AtomicInteger atomicInteger = new AtomicInteger();

    /**
     * 定义一个切入点
     */
    @Pointcut("execution(* com.study.spring_cloud.controller.HelloController.*(..))")
    public void webLog() {
        System.out.println("我又被调用了。" + atomicInteger.incrementAndGet());
    }

    @Before("webLog()")
    public void deBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("IP : " + request.getRemoteAddr());
        System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));

    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        System.out.println("方法的返回值 : " + ret);
    }

    /**
     * 后置异常通知
     */
    @AfterThrowing("webLog()")
    public void throwss(JoinPoint jp) {
        System.out.println("方法异常时执行.....");
    }

    /**
     * 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
     */
    @After("webLog()")
    public void after(JoinPoint jp) {
        System.out.println("方法最后执行.....");
    }

    /**
     * 环绕通知,环绕增强,相当于MethodInterceptor
     */
    @Around("webLog()")
    public Object arround(ProceedingJoinPoint pjp) {
        System.out.println("方法环绕start.....");
        try {
            Object o = pjp.proceed();
            System.out.println("方法环绕proceed,结果是 :" + o);
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值