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技术站