AOP业务
业务逻辑描述
日志记录
示例代码
AOP(Aspect Oriented Programming),面向切面编程,是一种将横向业务逻辑与纵向基础逻辑分离的编程模式。在实际项目中,AOP可以帮助我们避免代码重复、提高代码的可维护性和可扩展性,下面是AOP在项目中的常用场景和示例代码:
1、日志记录:
在方法执行前后记录方法的执行时间、请求参数和返回值等信息,以便于后续的系统运维和问题排查。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Aspect @Component public class LogAspect {
@Before("execution(* com.example.service.*.*(..))") public void before(JoinPoint joinPoint) { ... }
@AfterReturning(returning = "result", pointcut = "execution(* com.example.service.*.*(..))") public void after(JoinPoint joinPoint, Object result) { ... }
@AfterThrowing(throwing = "ex", pointcut = "execution(* com.example.service.*.*(..))") public void afterThrowing(JoinPoint joinPoint, Exception ex) { ... } }
|
2、权限控制
在方法执行前判断用户是否有访问该方法的权限,以及验证访问的参数是否合法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Aspect @Component public class AuthAspect {
@Before("execution(* com.example.controller.*.*(..))") public void checkAuth(JoinPoint joinPoint) { ... }
@Before("execution(* com.example.controller.*.*(..)) && args(userId)") public void checkUserId(String userId) { ... } }
|
3、统计方法执行次数和耗时
:在方法执行前后记录方法的执行时间、执行次数等信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| @Aspect @Component public class MetricsAspect {
private static final Logger logger = LoggerFactory.getLogger(MetricsAspect.class);
private final Map<String, AtomicInteger> counters = new ConcurrentHashMap<>(); private final Map<String, LongAdder> timers = new ConcurrentHashMap<>();
@Before("execution(* com.example.service.*.*(..))") public void recordCount(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); counters.computeIfAbsent(methodName, key -> new AtomicInteger(0)).incrementAndGet(); }
@Around("execution(* com.example.service.*.*(..))") public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable { String methodName =Point.getSignature().getName(); long startTime = System.currentTimeMillis(); try { return joinPoint.proceed(); } finally { long timeTaken = System.currentTimeMillis() - startTime; timers.computeIfAbsent(methodName, -> new LongAdder()).add(timeTaken); logger.debug("Method {} invoked in {} ms", methodName, timeTaken); } }
@Scheduled(fixedRate = 60000) public void logMetrics() { counters.forEach((methodName, value) -> logger.debug("Method {} invoked {} times", methodName, value.get())); timers.forEach((methodName, value) -> logger.debug("Method {} took {} ms in total methodName, value.sum())); } }
|
以上代码示例展示了如何使用 AOP 统计方法执行次数和耗时,定时输出统计信息。使用 AOP 统计方法执行次数和耗时,可以帮助我们了解系统中各种方法的工作情况,从而优化系统性能。
4、缓存处理
:对于频繁访问的方法,可以将调用的结果缓存起来,减少方法执行的时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Aspect @Component public class CacheAspect {
@Autowired private RedisTemplate<String, Object> redisTemplate;
@Around("execution(* com.example.service.*.*))") public Object cacheResult(ProceedingJoinPoint joinPoint) throws Throwable { // 缓存处理 String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); String key = generateKey(methodName, args); ValueOperations<String, Object> valueOps = redisTemplate.opsForValue(); if (redisTemplate.hasKey(key)) { return valueOps.get(key); } else { Object obj = joinPoint.proceed(); valueOps.set(key, obj); return obj; } }
private String generateKey(String methodName, Object[] args) { // 生成缓存键值 ... } }
|
5、事务管理
:对于需要进行事务回滚的方法,可以使用AOP来实现事务的管理和控制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Aspect @Component public class TransactionAspect {
@Autowired private PlatformTransactionManager transactionManager;
@Around("execution(* com.example.service.*.*))") public Object transactional(ProceedingJoinPoint joinPoint) { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = transactionManager.getTransaction(def); try { Object result = joinPoint.proceed(); transactionManager.commit(status); return result; } catch (Throwable e) { transactionManager.rollback(status); throw e; } } }
|
综上所述,AOP在项目中有很多应用场景,可以通过AOP优雅地解决一些横切性问题,避免代码重复,提高代码的可维护性和可扩展性。