【Spring】AOP是如何实现的?有哪些应用场景?
一、AOP的实现原理:
1.核心实现技术:
(1)动态代理模式:
- JDK动态代理:基于接口实现
public class JdkProxy implements InvocationHandler {
private Object target;
public Object createProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
System.out.println("Before method: " + method.getName());
Object result = method.invoke(target, args);
// 后置增强
System.out.println("After method: " + method.getName());
return result;
}
}
- CGLIB字节码增强:基于子类化实现(可代理无接口类)
public class CglibProxy implements MethodInterceptor {
public Object createProxy(Class<?> targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// 前置增强
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args);
// 后置增强
System.out.println("After method: " + method.getName());
return result;
}
}
(2)字节码操作(编译时/类加载时 织入)
- AspectJ:使用特殊编译器(ajc)或类加载时织入(LTW)
@Aspect
public class LoggingAspect {
@Pointcut("execution(* com.example.service.*.*(..))")
private void serviceMethods() {}
@Before("serviceMethods()")
public void logMethodCall(JoinPoint jp) {
System.out.println("调用方法: " + jp.getSignature().getName());
}
}
(3)拦截器模式
- Spring AOP:基于代理和拦截器链
public class CustomInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 前置处理
System.out.println("Before: " + invocation.getMethod().getName());
Object result = invocation.proceed();
// 后置处理
System.out.println("After: " + invocation.getMethod().getName());
return result;
}
}
2.实现流程:
1.定义切点(Pointcut):确定在哪些连接点插入横切逻辑。
2.编写通知(Advice):实现横切逻辑(前置/后置/环绕)。
3.配置织入(Weaving):将切面应用到目标对象。
- 编译期织入(AspectJ)
- 类加载期织入(AspectJ LTW)
- 运行时织入(Spring AOP)
二、AOP的应用场景:
1.日志记录
@Aspect
@Component
public class LoggingAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Pointcut("execution(* com.example..*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void controllerMethods() {}
@Around("controllerMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long elapsedTime = System.currentTimeMillis() - start;
logger.info("方法 {} 执行耗时: {} ms | 参数: {} | 返回: {}",
joinPoint.getSignature(),
elapsedTime,
Arrays.toString(joinPoint.getArgs()),
result);
return result;
}
}
2.事务管理
@Aspect
@Component
public class TransactionAspect {
@Autowired
private PlatformTransactionManager transactionManager;
@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
public void transactionalMethod() {}
@Around("transactionalMethod()")
public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
Object result = joinPoint.proceed();
transactionManager.commit(status);
return result;
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
}
}
3.权限控制
@Aspect
@Component
public class SecurityAspect {
@Pointcut("@annotation(com.example.RequiresPermission)")
public void permissionRequired() {}
@Before("permissionRequired()")
public void checkPermission(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
RequiresPermission annotation = signature.getMethod().getAnnotation(RequiresPermission.class);
if (!SecurityContext.hasPermission(annotation.value())) {
throw new AccessDeniedException("缺少权限: " + annotation.value());
}
}
}
4.性能监控
@Aspect
@Component
public class PerformanceAspect {
@Autowired
private MetricsService metricsService;
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
@Around("serviceMethods()")
public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
Timer.Sample sample = Timer.start();
try {
return joinPoint.proceed();
} finally {
sample.stop(metricsService.getTimer(methodName));
}
}
}
5.异常处理
@Aspect
@Component
public class ExceptionHandlingAspect {
@Pointcut("execution(* com.example..*(..))")
public void allMethods() {}
@AfterThrowing(pointcut = "allMethods()", throwing = "ex")
public void handleException(JoinPoint jp, Exception ex) {
String errorMsg = String.format("方法 %s 抛出异常: %s",
jp.getSignature(), ex.getMessage());
ErrorReporter.report(errorMsg, ex);
// 可添加异常转换逻辑
}
}
6.缓存管理
@Aspect
@Component
public class CachingAspect {
@Autowired
private CacheManager cacheManager;
@Pointcut("@annotation(com.example.Cacheable)")
public void cacheableMethods() {}
@Around("cacheableMethods()")
public Object handleCache(ProceedingJoinPoint joinPoint) throws Throwable {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
Cacheable annotation = method.getAnnotation(Cacheable.class);
String cacheName = annotation.value();
Cache cache = cacheManager.getCache(cacheName);
String key = generateKey(joinPoint.getArgs());
ValueWrapper cachedValue = cache.get(key);
if (cachedValue != null) {
return cachedValue.get();
}
Object result = joinPoint.proceed();
cache.put(key, result);
return result;
}
}