Java aop面向切面编程(aspectJweaver)案例详解

Java AOP面向切面编程(AspectJ Weaver)案例详解

什么是AOP?

AOP全称Aspect-Oriented Programming,即面向切面编程。它是一种基于OOP(Object-Oriented Programming,面向对象编程)的编程思想,用于解决模块化开发中横切关注点的问题,以通过对横切关注点进行抽象,实现系统各模块之间的解耦。

AOP中的概念

  • 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象,切面可以应用到多个对象上。
  • 连接点(Joinpoint):程序执行过程中明确的点,通常是方法的调用。
  • 通知(Advice):在特定的连接点上执行的增强处理,有before、after、around等不同类型。
  • 切入点(Pointcut):用于定义通知(Advice)被触发的连接点。
  • 引入(Introduction):在不修改类代码的前提下,引入新的接口。

AspectJ Weaver

AspectJ是AOP思想的实现框架之一,它提供了很多AOP的解决方案,并且使用起来比较方便。AspectJ Weaver是AspectJ工具集中的一个编译器,可以将AspectJ语言编写的切面加入到Java字节码文件中,AspectJ编译器会根据AspectJ语言编写的切面来增强Java字节码文件中的目标对象。

AspectJ Weaver案例详解

下面通过两个案例来详细讲解AspectJ Weaver的使用。

示例1:记录方法执行时间

我们通过AOP来记录方法的执行时间,以方便进行性能调优。我们可以使用AspectJ Weaver来实现,代码如下:

我们首先需要导入AspectJ Weaver依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

然后定义一个切面(Aspect)类,用于在方法调用前和调用后记录时间:

@Aspect
@Component
public class TimeAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(TimeAspect.class);

    @Around("execution(* com.example.demo.*.*(..))")
    public Object timeAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        LOGGER.info("Method {} cost {}ms.", joinPoint.getSignature().getName(), endTime - startTime);
        return result;
    }
}

在上述代码中,@Aspect注解表明该类是一个切面类,@Around注解表示在目标方法执行前和执行后会执行这个方法,execution表达式代表切入点,即要拦截哪些方法。

最后,在应用程序启动时,Spring会自动将切面注入到目标对象中,最终程序执行时会在记录方法执行时间。

示例2:缓存数据

我们通过AOP来实现数据的缓存,以提升程序的执行效率。代码实现如下:

在pom.xml文件中添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.8.8</version>
</dependency>

然后我们定义一个缓存切面类,用于缓存数据:

@Aspect
@Component
public class CacheAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(CacheAspect.class);

    // 创建Caffeine缓存对象
    private static final Cache<String, Object> CACHE = Caffeine.newBuilder()
            .expireAfterWrite(30, TimeUnit.SECONDS)
            .maximumSize(1000)
            .build();

    @Around("execution(* com.example.demo.UserServiceImpl.find*(..))")
    public Object findUserCache(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getName();
        Object[] args = joinPoint.getArgs();

        // 根据方法名和参数拼接Key
        StringBuilder sb = new StringBuilder();
        sb.append(methodName);
        for (Object arg : args) {
            sb.append(arg);
        }
        String key = sb.toString();

        // 判断缓存中是否存在
        Object result = CACHE.getIfPresent(key);
        if (result != null) {
            LOGGER.info("Method from cache, method:{} key:{}", methodName, key);
            return result;
        }

        try {
            LOGGER.info("Method from db, method:{} key:{}", methodName, key);
            // 缓存中不存在,从数据库查询
            result = joinPoint.proceed();

            // 将查询结果添加到缓存中
            CACHE.put(key, result);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        return result;
    }

}

在上述代码中,我们使用Caffeine缓存库创建了一个缓存对象,然后在@Around注解中定义了拦截的方法,通过方法名和参数拼接Key,判断是否存在缓存,如果存在直接返回缓存结果。如果缓存中不存在对应数据,则查询数据库并将结果添加到缓存中。

总结

通过上述示例,我们可以看到使用AspectJ Weaver进行AOP编程比较简单,可以方便地在Java类中增强逻辑。我们在实际项目中也可以灵活地应用AOP技术,提升程序效率和可维护性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java aop面向切面编程(aspectJweaver)案例详解 - Python技术站

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

相关文章

  • Java数据结构之集合框架与常用算法详解

    Java数据结构之集合框架与常用算法详解 引言 Java数据结构是将数据元素以某种逻辑关系组织在一起的数据整体,而集合框架是java.util包下的一组接口和类,用于存储和操作一组相同类型的数据。 在本文中,我们将全面了解Java集合框架,包括常用的集合接口、集合实现类和常见的集合算法。同时,我们还将介绍在Java中如何使用集合框架。 集合框架概述 Java…

    Java 2023年5月19日
    00
  • 一篇文章带你学习JAVA MyBatis底层原理

    一篇文章带你学习JAVA MyBatis底层原理 MyBatis是一个基于Java的ORM框架,它可以将数据库记录映射成对象,屏蔽了大部分的JDBC操作。文章将带你深入了解MyBatis底层原理。我们将分以下四个部分:解析MyBatis类结构、解析MyBatis配置文件、解析Mapper映射文件、MyBatis执行流程。 解析MyBatis类结构 MyBat…

    Java 2023年5月20日
    00
  • 基于String不可变字符与StringBuilder可变字符的效率问题

    当需要在应用程序中频繁操作字符串时,我们可以使用 String 类的字符串常量或 StringBuilder 可变字符类。虽然两种方式都可以操作字符,但它们之间具有不同的性能和效率。 String 类创建的字符串是不可变的字符序列。每次更改字符串时,都会创建一个新的字符串对象,因此需要更多的系统开销和内存来存储字符串,这会影响程序的性能。如果应用程序需要频繁…

    Java 2023年5月27日
    00
  • java字符串格式化(String类format方法)

    当我们需要将一个字符串和一些占位符组合起来形成一个新的字符串时,该怎么做呢?答案就是使用Java字符串格式化方法。Java字符串格式化方法可以让我们灵活地使用字符串格式化功能,将我们想要的内容组合成一个格式化好的字符串。 1. 字符串格式化的语法 Java字符串格式化方法使用占位符来表示要在新字符串中插入的值。以下是常见的占位符及其类型和示例: 占位符 类型…

    Java 2023年5月26日
    00
  • java 键盘输入的多种实现方法

    关于“Java键盘输入的多种实现方法”的攻略,下面就给您详细介绍: 使用 Scanner 类的 next() 方法进行输入 Scanner 是一个内置于 JDK 的类,专门用于输入处理。首先需要导入 java.util.Scanner 类。 示例代码: import java.util.Scanner; public class KeyboardInputD…

    Java 2023年5月18日
    00
  • spring boot2.0总结介绍

    Spring Boot 2.0 总结介绍 Spring Boot 作为一款基于 Spring 框架的快速开发框架,在各种 Web 应用开发过程中被广泛使用。此次我们将对 Spring Boot 2.0 进行总结介绍,分享如何快速搭建、配置和优化 Spring Boot 2.0。 快速搭建 Spring Boot 2.0 搭建 Spring Boot 2.0 …

    Java 2023年5月15日
    00
  • springboot springmvc抛出全局异常的解决方法

    下面是详细讲解“springboot springmvc抛出全局异常的解决方法”的完整攻略。 1. 场景描述 在开发Spring Boot和Spring MVC项目时,我们经常需要处理程序运行时的异常,这些异常可能会在控制器、服务或Spring Bean中发生。当运行时发生异常时,Spring Boot框架会抛出默认的异常界面,可能包含敏感信息,这不是我们想…

    Java 2023年5月27日
    00
  • Java中的Valid和Validated的比较内容

    当我们进行Java Bean校验时,通常会使用Hibernate提供的校验框架。Valid和Validated是该框架中最常用的两种表单验证注解,它们都是用于指定校验组,在校验时都可以用来限制哪些校验组中的校验规则生效。但是,它们有一些区别。下面我将详细讲解Java中Valid和Validated的比较内容,帮助读者理解它们的使用方法。 Valid注解 @V…

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