聊聊Spring——AOP详解(AOP概览)

我来详细讲解一下 "聊聊Spring——AOP详解(AOP概览)" 这篇文章的完整攻略。

什么是AOP

AOP(Aspect-Oriented Programming)是一种编程思想,它通过将横切关注点(Cross-cutting Concern)从主业务逻辑中分离出来,将其封装为一种独立的模块化方式,从而使程序结构更加清晰,维护更加方便。

AOP的术语

Join Point

Join Point(连接点)是指程序执行过程中的一个特定点,比如方法调用、异常抛出等。

Pointcut

Pointcut(切点)是指我们对哪些 Join Point 感兴趣,通常是通过表达式的方式指定。

Advice

Advice(通知)是指在切点上执行的代码,有 Before、After、Around、Throws 等多种类型。

Aspect

Aspect(切面)是切点和通知的组合体。

AOP的实现方式

经典的 AOP 实现方式有两种

基于动态代理的实现方式

Java JDK 提供了动态代理机制来实现 AOP,也可以使用第三方 JDK 动态代理库,比如 CGLIB。

代码示例:

public interface IUserService {
    public void addUser(String username, String password);
}

public class UserServiceImpl implements IUserService{
    public void addUser(String username, String password) {
        System.out.println("添加用户 " + username + "|" + password);
    }
}

public class LogInterceptor implements InvocationHandler {
    private Object target;

    public LogInterceptor(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始记录日志");
        Object result = method.invoke(target, args);
        System.out.println("结束记录日志");
        return result;
    }
}

public class Client {
    public static void main(String[] args) {
        IUserService userService = new UserServiceImpl();
        InvocationHandler handler = new LogInterceptor(userService);
        IUserService proxy = (IUserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), handler);
        proxy.addUser("lucy", "123456");
    }
}

基于字节码增强的实现方式

基于字节码增强的 AOP 实现方式,就是通过修改类的字节码,来实现切面逻辑。目前比较流行的字节码框架是 AspectJ。

代码示例:

public aspect LogAspect {
    pointcut addUser(String username, String password) : execution(* addUser(String, String)) && args(username, password);

    before(String username, String password) : addUser(username, password) {
        System.out.println("开始记录日志");
    }

    after(String username, String password) : addUser(username, password) {
        System.out.println("结束记录日志");
    }
}

public interface IUserService {
    public void addUser(String username, String password);
}

public class UserServiceImpl implements IUserService{
    public void addUser(String username, String password) {
        System.out.println("添加用户 " + username + "|" + password);
    }
}

public class Client {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        IUserService userService = (IUserService) ctx.getBean("userService");
        userService.addUser("lucy", "123456");
    }
}

总结

AOP 是一种非常重要的编程思想,可以让我们将公共代码模块化、解耦,从而提高程序的可维护性和可重用性。AOP 的实现方式有两种,基于动态代理的方式和基于字节码增强的方式。我们需要根据具体应用场景,选择合适的实现方式。

以上就是关于 "聊聊Spring——AOP详解(AOP概览)" 的完整攻略。

另外,我再来举一些示例:

示例1:使用AOP实现日志记录

@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(public * com.example.demo.controller..*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
       // 处理日志记录逻辑
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理日志记录逻辑
    }
}

示例2:使用AOP实现事务管理

@Component
@Aspect
public class TransactionAspect {

    @Pointcut("@annotation(com.example.demo.anno.Tranctional)")
    public void tranction() {
    }

    @Before("tranction()")
    public void doBefore(JoinPoint joinPoint) {
        // 开启数据库事务
    }

    @AfterReturning("tranction()")
    public void doAfterReturning(JoinPoint joinPoint) {
        // 提交数据库事务
    }

    @AfterThrowing("tranction()")
    public void doAfterThrowing(JoinPoint joinPoint) {
        // 回滚数据库事务
    }
}

以上就是两个使用AOP的示例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:聊聊Spring——AOP详解(AOP概览) - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Java方法参数传递如何实现

    Java 方法参数传递是值传递,即将实参的值复制一份传递给形参,方法中对形参的任何修改都不会影响实参的值。但对于引用类型变量,其实该变量存储的是对象在内存中的地址,这个地址也是一个值,因此传递引用类型变量时,实际上传递的是该地址值,也就是将内存中的对象地址复制一份传递给形参,此时形参和实参引用的是同一个对象,方法对形参所做的任何修改都会影响该对象的状态,从而…

    Java 2023年5月19日
    00
  • 使用@JsonFormat的一个坑及解决

    使用@JsonFormat注解可以自定义将Java对象转换为JSON字符串时的日期格式,但是在使用过程中也存在一个坑点。具体攻略如下: 1.问题描述 我们在使用@JsonFormat注解时,想要将日期格式化为类似”yyyy-MM-dd HH:mm:ss.SSS”的字符串格式,于是我们在实体类上添加该注解: public class User { privat…

    Java 2023年5月26日
    00
  • jsp中include指令静态导入和动态导入的区别详解

    JSP中include指令静态导入和动态导入的区别详解 在JSP中,我们可以使用include指令来包含其他的页面。include指令有两种导入方式:静态导入和动态导入。 静态导入 静态导入在JSP编译的时候就会被执行。即将被导入的页面会在编译期间被插入到包含该页面的页面中。因此,被导入的页面不能是动态生成的数据。下面是一个静态导入的示例: <%@ i…

    Java 2023年6月15日
    00
  • Java实现中国象棋的示例代码

    下面是“Java实现中国象棋的示例代码”的完整攻略: 1. 确定需求和分析 在实现中国象棋的过程中,需要先明确需求和进行分析。具体来说,我们需要了解中国象棋的规则、棋盘、棋子等基本信息,然后根据需求进行代码的设计和实现。 2. 代码设计 首先,我们需要了解如何存储和表示棋盘和棋子的信息。一般而言,可以使用二维数组来表示棋盘,然后用整数或字符来表示棋子的种类。…

    Java 2023年5月19日
    00
  • Java基础教程之对象的方法与数据成员

    Java基础教程之对象的方法与数据成员 对象是Java编程中的一个重要概念。对象可以看作是一个包含数据和方法的实体。数据成员是对象中的变量,存储对象的状态信息;方法是定义对象的行为的函数,用来对对象进行操作。 定义一个对象 在Java中,对象的定义通常包括以下步骤: 定义类(class) 定义数据成员(member variable) 定义方法(method…

    Java 2023年5月26日
    00
  • spring security需求分析与基础环境准备教程

    Spring Security需要分析与基础环境准备是学习Spring Security的基础部分,本文将分为两部分:需求分析和基础环境准备。 需求分析 目标用户:本篇教程适合Java开发者学习Spring Security。 目标技能:学习和掌握基础的Spring Security知识和使用方法,可以用于保护Web应用程序和REST API。 需求说明:学…

    Java 2023年5月20日
    00
  • 使用Java打印数字组成的魔方阵及字符组成的钻石图形

    下面我详细讲解一下“使用Java打印数字组成的魔方阵及字符组成的钻石图形”的完整攻略。 打印数字组成的魔方阵 思路 魔方阵是由 $n^2$ 个数字组成的方阵,其中每一行、每一列、每一条对角线上的数字之和都相等。我们可以使用以下的算法来生成 $n \times n$ 的魔方阵: 将数字 1 放在第一行的中间列。 依次将后续的数字放入前一个数字的右上角(如果已经…

    Java 2023年5月26日
    00
  • Java实现线程插队的示例代码

    实现线程插队可以使用Java中的join()方法。下面我将提供两个示例说明。 实现线程按照指定顺序执行 示例代码如下: class ThreadSequence implements Runnable { private int value; private Thread preThread; public ThreadSequence(int value,…

    Java 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部