Java中切面的使用方法举例详解

 更新时间:2025年03月10日 09:45:16   作者:心疼你的一切  
这篇文章主要介绍了Java中切面编程(AOP)的基本概念、原理及实现方式,AOP通过将横切关注点模块化为切面,使代码更易于维护和扩展,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在Java中,切面编程(Aspect-Oriented Programming, AOP)是一种编程范式,用于将横切关注点(如日志记录、事务管理、安全性等)从业务逻辑中分离出来。AOP通过将这些关注点模块化为“切面”,使代码更易于维护和扩展。

一、概念和原理

基本概念

切面(Aspect):一个切面是一个模块化的关注点集合,它包含了多个通知和切入点的定义。例如,日志切面会定义在哪些方法执行前后进行日志记录。

通知(Advice):通知定义了在切入点执行时要执行的代码逻辑,也就是在特定的连接点上执行的操作。常见的通知类型有前置通知、后置通知、环绕通知等。

切入点(Pointcut):切入点用于定义哪些连接点(程序执行过程中的特定位置,如方法调用、异常抛出等)会触发通知的执行。它可以通过方法名、类名、参数类型等条件进行精确匹配。

连接点(Join point):连接点是程序执行过程中可以插入切面的点,例如方法调用、字段访问等。在 Java 中,主要的连接点通常是方法调用。

AOP 实现方式及原理

1.基于代理的 AOP 实现(如 Spring AOP)

原理:Spring AOP 默认使用代理模式来实现 AOP 功能,有两种代理方式:JDK 动态代理和 CGLIB 代理。

JDK 动态代理:当目标对象实现了接口时,Spring AOP 会使用 JDK 动态代理。它基于 Java 的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。在运行时,JDK 动态代理会根据目标对象实现的接口动态生成一个代理类,该代理类实现了与目标对象相同的接口。当调用代理对象的方法时,会触发 InvocationHandler 的 invoke() 方法,在该方法中可以插入切面逻辑。

CGLIB 代理:当目标对象没有实现接口时,Spring AOP 会使用 CGLIB 代理。CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它通过继承目标对象的类来创建代理对象。在运行时,CGLIB 会动态生成一个目标对象的子类,并重写目标对象的方法,在重写的方法中插入切面逻辑。

代码如下:

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import java.lang.reflect.Method;

// 定义业务接口
interface BusinessService {
    void doBusiness();
}

// 实现业务接口
class BusinessServiceImpl implements BusinessService {
    @Override
    public void doBusiness() {
        System.out.println("执行核心业务逻辑");
    }
}

// 定义前置通知
class MyBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置通知:在方法执行前记录日志");
    }
}

public class AOPProxyExample {
    public static void main(String[] args) {
        // 创建目标对象
        BusinessService target = new BusinessServiceImpl();
        // 创建前置通知对象
        MyBeforeAdvice advice = new MyBeforeAdvice();
        // 创建代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        // 设置目标对象
        proxyFactory.setTarget(target);
        // 添加通知
        proxyFactory.addAdvice(advice);
        // 获取代理对象
        BusinessService proxy = (BusinessService) proxyFactory.getProxy();
        // 调用代理对象的方法
        proxy.doBusiness();
    }
}

二、基于字节码增强的 AOP 实现(如 AspectJ)

原理:AspectJ 是一个功能强大的 AOP 框架,它采用字节码增强的方式来实现 AOP。在编译时或类加载时,AspectJ 会修改目标类的字节码,将切面逻辑直接插入到目标类的方法中。与基于代理的实现方式不同,字节码增强不需要创建代理对象,而是直接在目标类的字节码中添加切面代码,因此性能更高,并且可以处理更多的连接点。

编译时织入:在编译 Java 源代码时,AspectJ 编译器(ajc)会对源代码进行处理,将切面逻辑织入到目标类的字节码中。这种方式需要使用 AspectJ 编译器来编译代码。

类加载时织入:在类加载时,通过 Java 的类加载器对目标类的字节码进行修改,将切面逻辑织入其中。这种方式不需要使用 AspectJ 编译器,只需要在运行时配置类加载器即可。

代码如下:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

// 定义切面类
@Aspect
public class LoggingAspect {
    // 定义切入点
    @Pointcut("execution(* com.example.BusinessService.*(..))")
    public void businessServiceMethods() {}

    // 定义前置通知
    @Before("businessServiceMethods()")
    public void beforeBusinessServiceMethod(JoinPoint joinPoint) {
        System.out.println("前置通知:在方法执行前记录日志,方法名:" + joinPoint.getSignature().getName());
    }
}

// 定义业务类
class BusinessService {
    public void doBusiness() {
        System.out.println("执行核心业务逻辑");
    }
}

public class AspectJExample {
    public static void main(String[] args) {
        BusinessService service = new BusinessService();
        service.doBusiness();
    }
}

总结 

到此这篇关于Java中切面的使用方法的文章就介绍到这了,更多相关JAVA中切面使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring框架通过工厂创建Bean的三种方式实现

    Spring框架通过工厂创建Bean的三种方式实现

    这篇文章主要介绍了Spring框架通过工厂创建Bean的三种方式实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • 解决javaBean规范导致json传参首字母大写将永远获取不到问题

    解决javaBean规范导致json传参首字母大写将永远获取不到问题

    这篇文章主要介绍了解决javaBean规范导致json传参首字母大写将永远获取不到问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • logback标记日志过滤器MarkerFilter源码解读

    logback标记日志过滤器MarkerFilter源码解读

    这篇文章主要为大家介绍了logback标记日志过滤器MarkerFilter源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Spring Boot自定义 Starter并推送到远端公服的详细代码

    Spring Boot自定义 Starter并推送到远端公服的详细代码

    这篇文章主要介绍了Spring Boot自定义 Starter并推送到远端公服,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • 谈谈Spring AOP中@Aspect的高级用法示例

    谈谈Spring AOP中@Aspect的高级用法示例

    在Spring AOP中目前只有执行方法这一个连接点,下面这篇文章主要给大家介绍了关于Spring AOP中@Aspect的高级用法的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-08-08
  • Java中调用Python的实现示例

    Java中调用Python的实现示例

    本文主要介绍了Java中调用Python的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Spring Boot快速过滤出一次请求的所有日志

    Spring Boot快速过滤出一次请求的所有日志

    这篇文章主要介绍了Spring Boot快速过滤出一次请求的所有日志,本文讲述了如何使用MDC工具来快速过滤一次请求的所有日志,并通过装饰器模式使得MDC工具在异步线程里也能生效,需要的朋友可以参考下
    2022-11-11
  • Java中如何利用Set判断List集合中是否有重复元素

    Java中如何利用Set判断List集合中是否有重复元素

    在开发工作中,我们有时需要去判断List集合中是否含有重复的元素,这时候我们不需要找出重复的元素,我们只需要返回一个 Boolean 类型就可以了,下面通过本文给大家介绍Java中利用Set判断List集合中是否有重复元素,需要的朋友可以参考下
    2023-05-05
  • Java8 使用 stream().sorted()对List集合进行排序的操作

    Java8 使用 stream().sorted()对List集合进行排序的操作

    这篇文章主要介绍了Java8 使用 stream().sorted()对List集合进行排序的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • SpringBoot中的自动配置原理详解

    SpringBoot中的自动配置原理详解

    这篇文章主要介绍了SpringBoot中的自动配置原理详解,springboot的自动配置类直观的表现就是通过一系列的注解,使得springboot项目在启动的时候从配置文件中加载需要自动配置的类,注入容器中,需要的朋友可以参考下
    2024-01-01

最新评论