【JAVA篇】------ spring aop

文章目录


AOP(面向切面编程)

💬欢迎交流:在学习过程中如果你有任何疑问或想法,欢迎在评论区留言,我们可以共同探讨学习的内容。你的支持是我持续创作的动力!
👍点赞、收藏与推荐:如果你觉得这篇文章对你有所帮助,请不要忘记点赞、收藏,并分享给更多的小伙伴!你们的鼓励是我不断进步的源泉!
🚀推广给更多人:如果你认为这篇文章对你有帮助,欢迎分享给更多对写作感兴趣的朋友,让我们一起进步,共同提升!

前言

AOP(面向切面编程)是一种通过分离横切关注点(如日志、事务、安全等)来增强程序模块化的编程范式。在Java中,AOP通常通过Spring等框架实现,通过切面将附加功能插入到业务逻辑中,减少代码冗余,提高可维护性。
本文我们主要来介绍AOP :

一、AOP的概念
  1. 定义
    AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,其主要思想是将一些跨越多个模块的功能(例如日志记录、安全验证、事务处理等)从主要的业务逻辑中提取出来。通过在程序运行时,将这些额外的代码(切面)巧妙地插入到目标对象的方法调用中,从而增强方法功能。

  2. 与OOP的对比
    面向对象编程(OOP)关注的是将数据和操作数据的逻辑封装到对象中,通过继承和多态等特性构建软件系统。而AOP则专注于处理分散在多个对象和方法中的横切关注点。例如,在一个复杂的Java企业级应用中,如果每个业务方法都需要记录日志,使用OOP会导致日志记录代码的重复,维护困难。AOP能够将日志记录功能提取出来,集中管理,避免代码重复。


二、AOP的核心概念
  1. 切面(Aspect)
    切面是将横切关注点抽象出来的一种模块。它包含通知(Advice)和切点(Pointcut)。切面定义了在哪些连接点(切点)执行哪些增强逻辑(通知)。例如,日志记录的切面定义了在哪些方法执行前后记录日志。

  2. 通知(Advice)
    通知是切面在目标方法执行时的具体增强逻辑。Java AOP中有五种通知类型:

    • 前置通知(Before Advice) :在目标方法执行之前执行。
    • 后置通知(After Advice) :在目标方法正常结束后执行。
    • 返回通知(After-Returning Advice) :目标方法返回值之后执行。
    • 异常通知(After-Throwing Advice) :目标方法抛出异常时执行。
    • 环绕通知(Around Advice) :可以在目标方法执行前后加入自定义逻辑,甚至控制是否调用目标方法。
    • 切点(Pointcut)
      切点用于定义通知的应用位置,通常通过切点表达式来指定。连接点是程序执行过程中的特定位置(如方法调用)。通过切点,可以确定在哪些连接点插入切面。
  3. 连接点(Join Point)
    连接点是程序执行过程中的一个位置,例如方法的调用、方法的执行等。在AOP中,切面代码会在这些连接点处进行织入。

  4. 织入(Weaving)
    织入是将切面应用到目标对象的过程,生成一个新的代理对象。Java中有不同的织入方式:编译时织入、类加载时织入、运行时织入。Spring AOP采用的是运行时织入,通过动态代理(JDK动态代理或CGLIB)将切面织入目标对象。


三、AOP在Java中的应用场景
  1. 日志记录
    AOP可用于在多个业务方法前后记录日志,而不需要在每个业务方法中重复编写日志记录代码。比如在Spring Web应用中,可以用AOP切面统一记录控制器方法的日志。

  2. 事务管理
    在企业级应用中,事务管理是重要的横切关注点。AOP可以用来在多个数据库操作方法之间自动开始、提交或回滚事务。例如,在Spring的业务层方法中,通过AOP配置事务切面,确保数据库操作的事务一致性。

  3. 安全检查
    AOP可以用于在方法执行前检查用户权限。比如,在某些资源管理系统中,通过AOP切面检查当前用户是否有权限执行某些敏感操作。


四、租房场景下的代理模式相关代码实现

1. 整体介绍

在找中介租房的场景中,可以使用代理模式来实现相关功能。这个场景涉及到租房接口、被代理对象(房东)、代理对象(中介)以及调用者(租客)。同时,探讨静态代理模式和动态代理模式(JDK动态代理)的实现及其优缺点。

2. 静态代理模式
  1. 抽象方法

    ```java
    package cn.icss.proxy;

    public interface ZuFang {
    void zuFang();
    }

    ```

  2. 被代理对象(房东)

    ```java
    package cn.icss.proxy;

    public class FangDong implements ZuFang {
    @Override
    public void zuFang() {
    System.out.println("图书馆向外出租500W一年");
    }
    }

    ```

  3. 代理对象(中介)

    ```java
    package cn.icss.proxy;

    /*
    * @author yishu
    * @create 2024-12-23 9:28
    * 代理对象
    /
    public class ZhongJie implements ZuFang {
    private String which;

    public String getWhich() {
        return which;
    }
    
    public void setWhich(String which) {
        this.which = which;
    }
    
    FangDong zhangsan = new FangDong();
    FangDong2 lisi = new FangDong2();
    
    @Override
    public void zuFang() {
        System.out.println("向我们收取中介费");
        if (which.equals("图书")) {
            zhangsan.zuFang();
        } else if (which.equals("演示")) {
            lisi.zuFang();
        }
        System.out.println("向房东收取介绍费");
        System.out.println("定期换床单20块");
    }
    

    }

    ```

  4. 调用者

    ```java
    package cn.icss.proxy;

    public class WoMen {
    public static void main(String[] args) {
    ZhongJie xiaowang = new ZhongJie();
    xiaowang.setWhich("演示");
    xiaowang.zuFang();
    }
    }

    ```

  5. 静态代理模式缺点
    当被代理对象数量增加时,代理代码会变得非常冗长,需要增加大量判断,降低代码的可维护性。


3. 动态代理模式(JDK动态代理)
  1. 修改后的代理对象

    ```java
    package proxy;

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;

    public class ZhongJie implements InvocationHandler {
    private Object fangDong;

    public Object getFangDong() {
        return fangDong;
    }
    
    public void setFangDong(Object fangDong) {
        this.fangDong = fangDong;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("向租客收取介绍费");
        Object result = method.invoke(fangDong, args);
        System.out.println("向房东收取介绍费");
        return result;
    }
    

    }

    ```

  2. 测试(调用者)

    ```java
    package proxy;

    import java.lang.reflect.Proxy;

    public class WoMen {
    public static void main(String[] args) {
    ZhongJie xiaowang = new ZhongJie();
    FangDong2 lisi = new FangDong2();
    xiaowang.setFangDong(lisi);

        ZuFang zuFang = (ZuFang) Proxy.newProxyInstance(
            WoMen.class.getClassLoader(), 
            new Class[]{ZuFang.class}, 
            xiaowang
        );
    
        zuFang.zuFang();
    }
    

    }

    ```

总结

AOP在Java开发中应用广泛,特别是在处理日志、事务、安全等横切关注点时,能够显著提高代码的复用性和可维护性。同时,代理模式作为一种设计模式,在租房场景中,静态代理和动态代理各有优缺点。通过动态代理可以减少代码的冗余,提高代码的扩展性和灵活性。

版权声明:程序员胖胖胖虎阿 发表于 2025年1月12日 下午7:36。
转载请注明:【JAVA篇】------ spring aop | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...