文章目录
- 一.什么是AOP
- 二.AOP的组成部分
- 三.SpringAOP的实现
- 3.1 增加SpringAOP依赖
- 3.2 创建切面
- 3.2 创建切点
- 3.3 创建通知
- 3.4 创建连接点
 
- 四.SpringAOP的实现原理
- 4.1 JDK动态代理
- 4.2 CGLIB 动态代理
- 总结
 
一.什么是AOP
AOP,全称为Aspect-Oriented Programming(面向切面编程),是一种编程范式和软件设计思想。它是面向对象编程(OOP)的一种补充和扩展,用于解决OOP中的一些横切关注点(cross-cutting concerns)问题。
 用一句话来概括的话,AOP (Aspect Oriented Programming)︰面向切面编程,它是一种思想,它是对某一类事情的集中处理。
二.AOP的组成部分
-  切面 
 我一般称之为类.这个切面值得就是具体的内容,一般来说,我们针对一个具体的内容,我们就称之为切面.举个例子来说,用户登录模块就是一个切面.
-  切点 
 切点,具体就是一个方法,它定义了拦截规则.
-  通知 
 如果说切点是方法的话,通知就是具体的一个实现代码.
 它里面有:
 1.前置通知:在目标方法(实际要执行的方法)调用之前执行的通知;
 2.后置通知:在目标方法调用之后执行的通知;
 3.环绕通知:在目标方法调用前、后都执行的通知l;
 4.异常通知:在目标方法抛出异常的时候执行的通知;
 5.返回通知:在目标方法返回的时候执行通知。
-  连接点 
 所有可能触发切点的点,就叫做连接点.
-  织入: 
 将切面应用到目标对象中的过程,可以在编译时、加载时或运行时进行
三.SpringAOP的实现
3.1 增加SpringAOP依赖
这里不是spring自带的aop依赖,我们要去下载springboot的aop依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.7.14</version>
</dependency>
3.2 创建切面
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect //切面
@Component //不能省略
public class UserAOP {
}
3.2 创建切点
//定义切点
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut() {
    }
3.3 创建通知
 //前置通知
    @Before("pointcut()")
    public void doBefore() {
        System.out.println("执行了前置通知:" + LocalDateTime.now());
    }
    // 后置通知
    @After("pointcut()")
    public void doAfter() {
        System.out.println("执行了后置通知:" + LocalDateTime.now());
    }
    // 环绕通知
    @Around("pointcut()")
    //把方法本身给它
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("开始执行环绕通知了");
        Object obj = joinPoint.proceed();
        System.out.println("结束环绕通知了");
        return obj;
    }
3.4 创建连接点
@RestController
public class UserController {
    @RequestMapping("/user/sayHi")
    public String sayHi(){
        System.out.println("执行了sayHi方法");
        return "hi spring boot aop.";
    }
    @RequestMapping("/user/login")
    public String Login(){
        System.out.println("执行了login方法");
        return "hi spring boot aop.";
    }
}


四.SpringAOP的实现原理
Spring AOP是构建在动态代理基础上,因此Spring对AOP的支持局限于方法级别的拦截。
 Spring AOP支持 JDK Proxy和CGLIB方式实现动态代理。默认情况下,实现了接口的类,使用AOP会基于JDK生成代理类,没有实现接口的类,会基于CGLIB生成代理类。
动态代理的常用实现方法有以下两种:
 此种实现在设计模式上称为动态代理模式,在实现的技术⼿段上,都是在 class 代码运⾏期,动
 态的织⼊字节码。
4.1 JDK动态代理
具体来说,当使用 JDK 动态代理时,需要定义一个实现 InvocationHandler 接口的类,并在该类中实现代理类的具体逻辑。然后,通过 Proxy.newProxyInstance() 方法来创建代理类的实例。该方法接受三个参数:类加载器、代理类要实现的接口列表和 InvocationHandler 对象
 代码如下:
import org.example.demo.service.AliPayService;
import org.example.demo.service.PayService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//动态代理:使用JDK提供的api(InvocationHandler、Proxy实现),此种方式实现,要求被代理类必须实现接口
public class PayServiceJDKInvocationHandler implements InvocationHandler {
    
    //目标对象即就是被代理对象
    private Object target;
    
    public PayServiceJDKInvocationHandler( Object target) {
        this.target = target;
    }
    
    //proxy代理对象
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //1.安全检查
        System.out.println("安全检查");
        //2.记录日志
        System.out.println("记录日志");
        //3.时间统计开始
        System.out.println("记录开始时间");
        //通过反射调用被代理类的方法
        Object retVal = method.invoke(target, args);
        //4.时间统计结束
        System.out.println("记录结束时间");
        return retVal;
    }
    public static void main(String[] args) {
        PayService target=  new AliPayService();
        //方法调用处理器
        InvocationHandler handler = 
            new PayServiceJDKInvocationHandler(target);
        //创建一个代理类:通过被代理类、被代理实现的接口、方法调用处理器来创建
        PayService proxy = (PayService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                new Class[]{PayService.class},
                handler
        );
        proxy.pay();
    }
}
4.2 CGLIB 动态代理
CGLIB 动态代理是一种使用 CGLIB 库来实现动态代理的技术。在 CGLIB 动态代理中,代理类不需要实现接口,而是通过继承被代理类来实现代理。 具体来说,当使用 CGLIB 动态代理时,需要定义一个继承被代理类的子类,并在该子类中实现代理类的具体逻辑。然后,通过 Enhancer.create() 方法来创建代理类的实例。该方法接受一个类作为参数,表示要代理的类,如下代码所示:
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.example.demo.service.AliPayService;
import org.example.demo.service.PayService;
import java.lang.reflect.Method;
public class PayServiceCGLIBInterceptor implements MethodInterceptor {
    //被代理对象
    private Object target;
    
    public PayServiceCGLIBInterceptor(Object target){
        this.target = target;
    }
    
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //1.安全检查
        System.out.println("安全检查");
        //2.记录日志
        System.out.println("记录日志");
        //3.时间统计开始
        System.out.println("记录开始时间");
        //通过cglib的代理方法调用
        Object retVal = methodProxy.invoke(target, args);
        //4.时间统计结束
        System.out.println("记录结束时间");
        return retVal;
    }
    
    public static void main(String[] args) {
        PayService target=  new AliPayService();
        PayService proxy= (PayService) Enhancer.create(target.getClass(),new PayServiceCGLIBInterceptor(target));
        proxy.pay();
    }
}
总结
综上所述,动态代理的实现方法主要有 JDK 动态代理和 CGLIB 动态代理。JDK 动态代理中,代理类必须实现一个或多个接口,而 CGLIB 动态代理中,代理类不需要实现接口,但代理类不能是 final 类型,因为它是通过定义一个被代理类的子类来实现动态代理的,因此开发者需要根据具体的需求选择合适的技术来实现动态代理。









![[CrackMe]damn.exe的逆向及注册机编写](https://img-blog.csdnimg.cn/31d5480024d741e5a9e0839ad87fab2e.png)








![[NLP]LLM高效微调(PEFT)--LoRA](https://img-blog.csdnimg.cn/ca73a8eb85aa43b782100ca6210f34e9.png)
