> 文章列表 > AOP除了日志记录外,还可以用于缓存管理、权限控制、性能控制、异常处理

AOP除了日志记录外,还可以用于缓存管理、权限控制、性能控制、异常处理

AOP除了日志记录外,还可以用于缓存管理、权限控制、性能控制、异常处理

除了日志记录外,AOP还可以用于以下情况:

缓存管理:通过AOP,可以将缓存逻辑从业务逻辑中分离出来,实现缓存的统一管理和更高效的数据读取。例如,使用AOP实现缓存切面,可以在方法执行前检查缓存中是否有数据,如果有,则直接从缓存中读取数据并返回,否则执行方法并将结果存入缓存中。

权限控制:通过AOP,可以将权限控制逻辑从业务逻辑中分离出来,实现统一的权限管理和更好的安全性。例如,使用AOP实现权限控制切面,可以在方法执行前检查用户的权限,如果有权限,则允许执行方法,否则拒绝执行。

性能监控:通过AOP,可以实现统一的性能监控和更好的性能优化。例如,使用AOP实现性能监控切面,可以在方法执行前记录当前时间戳,并在方法执行后计算方法执行时间,并将结果输出到日志中,从而帮助开发人员识别慢速代码并进行优化。

异常处理:通过AOP,可以将异常处理逻辑从业务逻辑中分离出来,实现统一的异常处理和更好的代码健壮性。例如,使用AOP实现异常处理切面,可以在方法执行过程中检查异常并进行相应的处理,例如将异常信息记录到日志中、发送邮件通知等。

缓存的例子

// 定义缓存注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Cached {String value();
}
// 定义缓存切面
@Aspect
@Component
public class CacheAspect {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Around("@annotation(cached)")public Object cache(ProceedingJoinPoint joinPoint, Cached cached) throws Throwable {String key = cached.value();Object result = redisTemplate.opsForValue().get(key);if (result != null) {return result;}result = joinPoint.proceed();redisTemplate.opsForValue().set(key, result);return result;}
}

// 使用缓存注解
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;@Cached("userCache")@Overridepublic User getUserById(int id) {return userDao.getUserById(id);}
}

在这个例子中,我们定义了一个@Cached注解,用于标记需要缓存的方法。然后,我们实现了一个缓存切面,使用@Around注解将切面应用到@Cached注解标记的方法上。在缓存切面中,我们首先检查缓存中是否存在该数据,如果存在,则直接从缓存中读取并返回,否则执行该方法并将结果存入缓存中。最后,我们在UserServiceImpl类的getUserById方法上使用@Cached注解标记该方法需要缓存。

这个例子中使用了Redis作为缓存存储,当然也可以使用其他缓存方案,例如Ehcache、Memcached等。

性能控制的例子

添加依赖

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

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-core</artifactId></dependency><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency>

上述依赖中包含Micrometer核心库和Prometheus度量系统的集成库。

定义一个切面类,使用@Aspect注解表示这是一个切面,使用@Component注解将其注册为Spring Bean。

配置Micrometer

然后,在你的Spring Boot应用程序中,你可以添加以下配置类来创建MeterRegistry bean:

@Configuration
public class MetricsConfig {@Beanpublic MeterRegistry meterRegistry() {return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);}
}

这个配置类使用PrometheusMeterRegistry来创建一个MeterRegistry bean,并使用默认的PrometheusConfig配置。当你运行你的应用程序时,你应该可以看到指标被收集并发布到Prometheus中了。

在application.yml文件中添加Micrometer相关配置:

management:metrics:tags:app: myappexport:prometheus:enabled: true

这里配置了app标签,用于标识应用程序,以及启用了Prometheus导出器。

定义切面

package com.wg.myAspect;import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import java.time.Duration;/ @author lst* @date 2023/4/18 10:54* @return null*/
@Aspect
@Component
public class PerformanceAspect {private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);private final Timer timer;public PerformanceAspect(MeterRegistry registry) {this.timer = registry.timer("app.service.method.execution.time");}//    @Around("execution(* com.wg.controller..*.*(..))")@Around("execution(* com.wg.controller.UserController.*(..))")public Object monitor(ProceedingJoinPoint joinPoint) throws Throwable {Timer.Sample sample = Timer.start();Object result = joinPoint.proceed();long durationNanos = sample.stop(this.timer);Duration duration = Duration.ofNanos(durationNanos);long durationSeconds = duration.toSeconds();String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getSimpleName();logger.info("Method {} in class {} took {} seconds to execute", methodName, className, durationSeconds);return result;}
}

抖团网