设计注解
- 定义注解:使用
@Retention
和@Target
元注解来定义自定义注解。@Retention
指定注解的保留策略,@Target
指定注解可以应用的目标类型。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
// 可以定义一些属性
String value() default "";
}
- 在目标方法上使用注解:在需要应用切面逻辑的方法上添加自定义注解。
import org.springframework.stereotype.Service;
@Service
public class MyService {
@MyAnnotation("example")
public void myMethod() {
// 业务逻辑
}
}
实现AOP切面
- 创建切面类:使用
@Aspect
注解定义切面类,在切面类中定义切入点和通知。
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
// 定义切入点
@Around("@annotation(myAnnotation)")
public Object aroundAdvice(ProceedingJoinPoint joinPoint, MyAnnotation myAnnotation) throws Throwable {
// 前置处理
System.out.println("Before method execution, value from annotation: " + myAnnotation.value());
try {
// 执行目标方法
return joinPoint.proceed();
} catch (Throwable e) {
// 异常处理
System.out.println("Exception occurred during method execution: " + e.getMessage());
throw e;
} finally {
// 后置处理
System.out.println("After method execution");
}
}
}
- 切入点:
@Around("@annotation(myAnnotation)")
表示切入点为所有被@MyAnnotation
注解的方法,其中myAnnotation
是切入点表达式中的参数,在通知方法中作为参数使用。
- 通知类型:这里使用了
@Around
环绕通知,它可以在目标方法执行前后执行自定义逻辑,并且可以控制目标方法是否执行以及处理目标方法的返回值和异常。
实际项目中的优势
- 代码复用性:通过将通用逻辑抽取到切面中,避免在多个业务方法中重复编写相同的逻辑,提高代码复用率。例如,日志记录、权限检查等逻辑可以通过切面统一处理。
- 代码可维护性:业务逻辑和切面逻辑分离,当切面逻辑需要修改时,只需要修改切面类,而不影响业务代码,降低维护成本。
- 提高系统扩展性:方便在不改变现有业务代码的基础上,添加新的切面逻辑,如性能监控、事务管理等,使系统更具扩展性。
适用场景
- 日志记录:记录方法的调用信息、参数、返回值等,方便系统调试和问题排查。
- 权限控制:在方法调用前检查用户是否具有相应的权限,防止非法访问。
- 事务管理:在方法执行前后开启和提交事务,确保数据的一致性和完整性。
- 性能监控:统计方法的执行时间,找出性能瓶颈,优化系统性能。