AspectJ 在项目中的集成应用代码案例
1. 添加 AspectJ 依赖
在 Maven 项目的 pom.xml
文件中添加以下依赖:
<dependencies><!-- AspectJ Weaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version></dependency><!-- AspectJ 运行时 --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.6</version></dependency>
</dependencies>
2. 创建切面类
创建一个切面类,用于定义日志记录和性能监控的逻辑。
日志记录切面
package com.example.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {// 定义切点,匹配 com.example.service 包下所有类的所有方法@Pointcut("execution(* com.example.service.*.*(..))")public void serviceMethods() {}// 前置通知@Before("serviceMethods()")public void logBefore(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getName();System.out.println("Before: Calling method " + methodName + " in class " + className);}// 后置通知@After("serviceMethods()")public void logAfter(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();System.out.println("After: Method " + methodName + " executed");}// 返回通知@AfterReturning(pointcut = "serviceMethods()", returning = "result")public void logAfterReturning(JoinPoint joinPoint, Object result) {String methodName = joinPoint.getSignature().getName();System.out.println("AfterReturning: Method " + methodName + " returned with result: " + result);}// 异常通知@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {String methodName = joinPoint.getSignature().getName();System.out.println("AfterThrowing: Method " + methodName + " threw exception: " + ex.getMessage());}
}
性能监控切面
package com.example.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import java.util.logging.Logger;@Aspect
@Component
public class PerformanceMonitorAspect {private static final Logger logger = Logger.getLogger(PerformanceMonitorAspect.class.getName());// 定义切点,匹配 com.example.service 包下所有类的所有方法@Pointcut("execution(* com.example.service.*.*(..))")public void serviceMethods() {}// 环绕通知@Around("serviceMethods()")public Object profile(ProceedingJoinPoint pjp) throws Throwable {long startTime = System.currentTimeMillis();Object result = pjp.proceed(); // 调用目标方法long elapsedTime = System.currentTimeMillis() - startTime;logger.info("Method execution time: " + elapsedTime + " ms for method: " + pjp.getSignature().toShortString());return result;}
}
3. 创建服务类
创建一个简单的服务类,用于测试切面功能。
package com.example.service;import org.springframework.stereotype.Service;@Service
public class MyService {public String doSomething() {System.out.println("Executing doSomething method");return "Result";}
}
4. 测试
在主程序或测试类中调用服务类的方法,验证切面是否生效。
package com.example;import com.example.service.MyService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Main {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.example");MyService myService = context.getBean(MyService.class);myService.doSomething();context.close();}
}
输出示例
运行程序后,控制台输出类似以下内容:
Before: Calling method doSomething in class com.example.service.MyService
Executing doSomething method
AfterReturning: Method doSomething returned with result: Result
After: Method doSomething executed
Method execution time: 10 ms for method: doSomething()
说明
-
日志记录切面:通过
@Before
、@After
、@AfterReturning
和@AfterThrowing
注解,分别在方法执行前后、返回后和抛出异常后记录日志。 -
性能监控切面:通过
@Around
注解,记录方法的执行时间。 -
切点表达式:
execution(* com.example.service.*.*(..))
表示匹配com.example.service
包下所有类的所有方法。
通过以上代码,你可以轻松地在 Spring 项目中集成 AspectJ,实现日志记录、性能监控等功能,而无需修改业务逻辑代码