JAVA中切面的使用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: AOP(面向切面编程)通过切面、通知、切入点和连接点实现模块化关注点分离。Spring AOP基于代理模式,使用JDK动态代理或CGLIB代理;AspectJ采用字节码增强,在编译或类加载时织入切面逻辑,性能更高。示例代码展示了如何在方法调用前后插入日志记录等操作。
  1. 基本概念
    切面(Aspect):一个切面是一个模块化的关注点集合,它包含了多个通知和切入点的定义。例如,日志切面会定义在哪些方法执行前后进行日志记录。
    通知(Advice):通知定义了在切入点执行时要执行的代码逻辑,也就是在特定的连接点上执行的操作。常见的通知类型有前置通知、后置通知、环绕通知等。
    切入点(Pointcut):切入点用于定义哪些连接点(程序执行过程中的特定位置,如方法调用、异常抛出等)会触发通知的执行。它可以通过方法名、类名、参数类型等条件进行精确匹配。
    连接点(Join point):连接点是程序执行过程中可以插入切面的点,例如方法调用、字段访问等。在 Java 中,主要的连接点通常是方法调用。
  2. AOP 实现方式及原理
    2.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();
    }
}
  1. 基于字节码增强的 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();
    }
}
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
Java 开发者 Spring
[Java]自定义注解
本文介绍了Java中的四个元注解(@Target、@Retention、@Documented、@Inherited)及其使用方法,并详细讲解了自定义注解的定义和使用细节。文章还提到了Spring框架中的@AliasFor注解,通过示例帮助读者更好地理解和应用这些注解。文中强调了注解的生命周期、继承性和文档化特性,适合初学者和进阶开发者参考。
104 14
|
7月前
|
缓存 Java 测试技术
day27:Java零基础 - 动态代理
【7月更文挑战第27天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
51 2
day27:Java零基础 - 动态代理
|
7月前
|
设计模式 监控 Java
Java中的动态代理:实现与应用
Java中的动态代理:实现与应用
|
9月前
|
XML Java 编译器
Java的注解
Java的注解
|
9月前
|
监控 Java 数据安全/隐私保护
Java中的动态代理
Java中的动态代理
47 0
|
设计模式 Java API
Java JDK动态代理
Java JDK动态代理
118 0
动态代理—Java
动态代理—Java
100 0
动态代理—Java
|
Java 开发者
Java-JDK动态代理
Java-JDK动态代理
72 0
|
XML 架构师 安全
java中《自定义注解》的使用
定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释 补充导读:相信很多同学看完之后是整不明白的,为什么呢是因为我们用专业名词去解释了专业名词,所以你才会不懂的,那么我们该怎么办呢
586 0
|
Java 黑灰产治理 Spring
java | 什么是动态代理?
最近在复习 Java 相关,回顾了下代理模式。代理模式在 Java 领域很多地方都有应用,它分为静态代理和动态代理,其中 Spring AOP 就是动态代理的典型例子。动态代理又分为接口代理和 cglib (子类代理),结合我的理解写了几个 demo 分享给你们,这是昨晚修仙到 3 点写出来的文章,不点在看,我觉得说不过去了。
java | 什么是动态代理?

热门文章

最新文章