【关于Spring那些事】——带你了解Spring AOP的代理模式

简介: 代理摸式是一种设计横式,提供了对目标对象额外的访问开式,即通过代理对象来实现对目标对象的访问,能够在不修改原目标对象的前提下提供额外的功能操作,实现对目标对象的功能扩展。简单来说,代理模式就是设置一个中间代理来控制访问原目标对象,从而增加原对象的功能和简化访问方式。

一、静态代理

静态代理,代理类和被代理的类实现了同样的接口,只能代理特定的类。
  1. 定义一个接口
public interface Service {
    public void delete();
    public void update();
    public void insert();
}
  1. 被代理类
public class StudentServiceImpl implements Service {
    @Override
    public void delete() {
        System.out.println("删除学生信息!!!");
    }

    @Override
    public void update() {
        System.out.println("修改学生信息!!!");
    }

    @Override
    public void insert() {
        System.out.println("添加学生信息!!!");
    }
}
  1. 代理类
public class StaticProxy implements Service {

    private Service service;

    public StaticProxy(Service service) {
        this.service = service;
    }

    public void delete() {
        open();
        service.delete();
        commit();
    }

    public void update() {
        open();
        service.update();
        commit();
    }

    public void insert() {
        open();
        service.insert();
        commit();
    }

    public void open(){
        System.out.println("开启事务!!!");
    }
    public void commit(){
        System.out.println("提交事务!!!");
    }

}

4.测试类

public class Test {
    public static void main(String[] args) {
        //被代理类
        StudentServiceImpl student = new StudentServiceImpl();
        //被代理类的代理对象
        StaticProxy proxy = new StaticProxy(student);
        //通过代理对象调用被代理类的方法
        proxy.delete();
    }
}

运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1tskzJql-1650096958348)(img_1.png)]

被代理类只需负责自己特定的业务,而代理类则负责业务的扩展,比如执行被代理类的方法前要开启事务,执行之后要提交事务,我们就不需要给每个方法都添加开启事务和提交事务。
代理类就会负责完成这些工作。

静态代理的优缺点:

  1. 优点:
  • 被代理类只需负责核心业务
  • 业务逻辑的扩展更加方便
  • 通用代码放到代理类中,提高了代码的复用性
  1. 缺点:

    • 被代理类太多,就会导致工作量变大,开发效率降低

二、动态代理

动态代理,由AOP框架动态生成的一的对象,对象可以作为目标对象使用。
动态代理有两种方式:

  • JDK动态代理
  • CGLIB代理

2.1 JDK动态代理

基于接口的动态代理,只能为实现了接口的类动态代理对象

  • 创建一个接口并创建一个它的实现类并重写它的方法。
  • 创建一个类实现InvocationHandler接口,并重写invoke方法
public class JdkDynamicProxy implements InvocationHandler {
    //被代理的对象
    private Object object;

    public JdkDynamicProxy(Object object) {
        this.object = object;
    }
    //产生代理对象,返回代理对象
    public Object getProxy(){
        //1.获取被代理对象的类加载器
        ClassLoader classLoader = object.getClass().getClassLoader();
        //2.获取被代理对象实现的所有接口
        Class<?>[] interfaces = object.getClass().getInterfaces();
        //3.创建代理对象
        //classloader:类加载器来定义代理类
        //interfaces:代理类实现的接口列表
        //this:调度方法调用的调用处理函数
        Object o = Proxy.newProxyInstance(classLoader, interfaces,this);
        return o;
    }
    //处理代理实例,返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object invoke = method.invoke(object,args);
        return invoke;
    }
    //定义一个打印日志的方法
    public void log(String msg){
        System.out.println("执行了"+ msg +"方法!");
    }
}
  • 测试
public class DynamicProxyTest {
    public static void main(String[] args) {
        //创建被代理类对象
        StudentServiceImpl studentService = new StudentServiceImpl();
        //创建代理对象,产生的代理对象可以强转成被代理对象实现的接口类型
        JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(studentService);
        Service proxy = (Service) jdkDynamicProxy.getProxy();
        //使用代理对象调方法,不会执行调用的方法,而是进入到创建代理对象时指定的invoke方法
        //调用的方法作为一个参数,传给invoke方法
        proxy.delete();
    }
}

运行结果:
在这里插入图片描述

2.2 CGLib代理

使用JDK动态代理的对象必须是实现了一个或多个接口的,如果要对没有实现接口的类创建代理对象,就要使用CGLIB代理。
基于类的动态代理—CGlib
  • CGLib是一个高性能开源的代码生成包,因在Spring的核心包中已包含CGLib所需要的包,所以不再需要添加依赖。
  • 创建一个StudentServiceImpl 类,并添加增删改方法。
  • 创建一个类,实现MethodInterceptor接口,并重写intercept方法。
/**
 * CGLIB代理
 */
public class CGLibDynamicProxy implements MethodInterceptor {

    private Object object;

    public CGLibDynamicProxy(Object object) {
        this.object = object;
    }
    //创建并返回代理对象
    //该代理对象是通过被代理类的子类来创建的
    public Object getProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        log(method.getName());
        Object invoke = method.invoke(object, args);
        return invoke;
    }

    //定义一个打印日志的方法
    public void log(String msg){
        System.out.println("执行了"+ msg +"方法!");
    }
}
  • 测试
public class DynamicProxyTest {
    public static void main(String[] args) {
        //创建被代理类对象
        StudentServiceImpl studentService = new StudentServiceImpl();
        //创建代理对象,产生的代理对象可以强转成被代理类类型
        CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(studentService);
        StudentServiceImpl proxy = (StudentServiceImpl) cgLibDynamicProxy.getProxy();
        //使用代理对象调方法,不会执行调用的方法,而是进入到创建代理对象时指定的intercept方法
        //将调用的方法以及方法中的参数传给intercept方法
        proxy.insert();
    }
}

运行结果:
在这里插入图片描述
动态代理的优点:

  • 被代理类只需负责核心业务;
  • 业务逻辑的扩展更加方便;
  • 通用代码放到代理类中,提高了代码的复用性;
  • 一个动态代理 , 一般代理某一类业务;
  • 一个动态代理可以代理多个类,代理的是接口。
相关文章
|
27天前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
271 0
|
5月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
|
2月前
|
人工智能 监控 安全
Spring AOP切面编程颠覆传统!3大核心注解+5种通知类型,让业务代码纯净如初
本文介绍了AOP(面向切面编程)的基本概念、优势及其在Spring Boot中的使用。AOP作为OOP的补充,通过将横切关注点(如日志、安全、事务等)与业务逻辑分离,实现代码解耦,提升模块化程度、可维护性和灵活性。文章详细讲解了Spring AOP的核心概念,包括切面、切点、通知等,并提供了在Spring Boot中实现AOP的具体步骤和代码示例。此外,还列举了AOP在日志记录、性能监控、事务管理和安全控制等场景中的实际应用。通过本文,开发者可以快速掌握AOP编程思想及其实践技巧。
|
2月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
2月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
9月前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
424 6
|
8月前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
379 25
|
8月前
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
283 24
|
7月前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
762 0
|
7月前
|
Java 开发者 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——什么是AOP
本文介绍了Spring Boot中的切面AOP处理。AOP(Aspect Oriented Programming)即面向切面编程,其核心思想是分离关注点。通过AOP,程序可以将与业务逻辑无关的代码(如日志记录、事务管理等)从主要逻辑中抽离,交由专门的“仆人”处理,从而让开发者专注于核心任务。这种机制实现了模块间的灵活组合,使程序结构更加可配置、可扩展。文中以生活化比喻生动阐释了AOP的工作原理及其优势。
365 0