日志记录,性能统计,安全控制,权限管理,事务处理,异常处理,资源池管理。
package com.example.demo.aop;
import com.example.demo.model.SysLog;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
// @Autowired
// private SysLog sysLog;
@Pointcut("@annotation(com.springboot.annotation.Log)")表示在被@Log注解标记的方法上进行拦截。
@Pointcut("@annotation(com.example.demo.annotation.Log)")
public void pointcut() {
}
@Around("(pointcut())")
public void around(ProceedingJoinPoint point) {
long beginTime = System.currentTimeMillis();
try {
// 执行方法
point.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 保存日志
System.out.println("执行的方法"+point.getSignature().getName());
System.out.println("执行的时间"+time);
// sysLog.setId(11);
// System.out.println(sysLog);
}
}
当使用切面编程时,切面可以用于以下常见的场景:
切面可以用来记录应用程序的运行日志,例如记录方法的调用、参数信息、返回值等。以下是一个使用切面记录日志的示例代码:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("Before executing method: " + methodName);
}
@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("After executing method: " + methodName);
System.out.println("Method returned: " + result);
}
}
切面可以用于统计方法的执行时间,帮助我们找出应用程序中的性能瓶颈。以下是一个使用切面进行性能统计的示例代码:
@Aspect
@Component
public class PerformanceAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object measurePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
String methodName = joinPoint.getSignature().getName();
System.out.println("Method " + methodName + " execution time: " + executionTime + "ms");
return result;
}
}
切面可以用于实现安全控制和权限管理,例如检查用户是否具有执行某个方法的权限。以下是一个使用切面进行权限管理的示例代码:
@Aspect
@Component
public class SecurityAspect {
@Before("@annotation(com.example.annotation.RequiresPermission)")
public void checkPermission(JoinPoint joinPoint) {
// 检查用户是否具有执行该方法的权限
// 如果没有权限,可以抛出异常或进行其他处理
}
}
切面可以用于实现事务处理,例如在方法执行前开启事务,在方法执行后提交或回滚事务。以下是一个使用切面进行事务处理的示例代码:
@Aspect
@Component
public class TransactionAspect {
@Around("@annotation(org.springframework.transaction.annotation.Transactional)")
public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
// 开启事务
// 执行方法
// 提交或回滚事务
}
}
切面可以用于统一处理方法中的异常,例如记录日志、发送通知或进行其他异常处理操作。以下是一个使用切面进行异常处理的示例代码:
@Aspect
@Component
public class ExceptionAspect {
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
public void handleException(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("Exception occurred in method: " + methodName);
System.out.println("Exception message: " + ex.getMessage());
// 其他异常处理操作
}
}
切面可以用于管理资源池,例如连接池、线程池等。以下是一个使用切面管理资源池的示例代码:
@Aspect
@Component
public class ResourcePoolAspect {
@Around("@annotation(com.example.annotation.ResourcePool)")
public Object manageResourcePool(ProceedingJoinPoint joinPoint) throws Throwable {
// 从资源池中获取资源
// 执行方法
// 将资源归还到资源池
}
}
切面编程的灵活性和可定制性使得我们能够根据实际情况将其应用于各种不同的场景中。
@Service
public class UserService {
public void createUser(User user) {
// 创建用户
}
public User getUserById(long id) {
// 根据ID获取用户
return null;
}
// 其他方法...
}
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.UserService.*(..))")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("Before executing method: " + methodName);
}
@AfterReturning(pointcut = "execution(* com.example.service.UserService.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("After executing method: " + methodName);
System.out.println("Method returned: " + result);
}
}
例如,当我们调用createUser方法时,日志输出可能如下所示:
Before executing method: createUser
After executing method: createUser
Method returned: null
@Service
public class OrderService {
public List<Order> getOrdersByUserId(long userId) {
// 根据用户ID获取订单列表
return null;
}
public void createOrder(Order order) {
// 创建订单
}
// 其他方法...
}
@Aspect
@Component
public class PerformanceAspect {
@Around("execution(* com.example.service.OrderService.*(..))")
public Object measurePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
String methodName = joinPoint.getSignature().getName();
System.out.println("Method " + methodName + " execution time: " + executionTime + "ms");
return result;
}
}
例如,当我们调用getOrdersByUserId方法时,控制台输出可能如下所示:
Method getOrdersByUserId execution time: 10ms
@Service
public class ArticleService {
@RequiresPermission("article.create")
public void createArticle(Article article) {
// 创建文章
}
@RequiresPermission("article.view")
public Article getArticleById(long id) {
// 根据ID获取文章
return null;
}
// 其他方法...
}
@Aspect
@Component
public class SecurityAspect {
@Before("@annotation(com.example.annotation.RequiresPermission)")
public void checkPermission(JoinPoint joinPoint) {
// 检查用户是否具有执行该方法的权限
// 如果没有权限,可以抛出异常或进行其他处理
String permission = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
if (!hasPermission(permission)) {
throw new SecurityException("Permission denied for method: " + permission);
}
}
private boolean hasPermission(String permission) {
// 检查当前用户是否具有指定权限
// 实际实现中可能需要从数据库或缓存中获取权限列表,并进行校验
return true;
}
}
例如,当我们调用createArticle方法时,并且当前用户没有article.create权限时,将会抛出SecurityException异常。
@Service
@Transactional
public class AccountService {
public void transferMoney(long fromAccountId, long toAccountId, double amount) {
// 从一个账户向另一个账户转账
}
public void withdrawMoney(long accountId, double amount) {
// 从一个账户取款
}
// 其他方法...
}
@Aspect
@Component
public class TransactionAspect {
@Autowired
private PlatformTransactionManager transactionManager;
@Around("@annotation(org.springframework.transaction.annotation.Transactional)")
public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(definition);
try {
Object result = joinPoint.proceed();
transactionManager.commit(status);
return result;
} catch (Throwable ex) {
transactionManager.rollback(status);
throw ex;
}
}
}
@Service
public class MailService {
public void sendMail(Mail mail) {
// 发送邮件
}
public void deleteMail(long id) {
// 根据ID删除邮件
throw new RuntimeException("Unable to delete mail: " + id);
}
// 其他方法...
}
@Aspect
@Component
public class ExceptionAspect {
@AfterThrowing(pointcut = "execution(* com.example.service.MailService.*(..))", throwing = "ex")
public void handleException(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("Exception occurred in method: " + methodName);
System.out.println("Exception message: " + ex.getMessage());
// 其他异常处理操作,例如记录日志、发送通知等
}
}
例如,当我们调用deleteMail方法时,并且出现了运行时异常时,控制台输出可能如下所示:
Exception occurred in method: deleteMail
Exception message: Unable to delete mail: 123