当前位置: 首页 > news >正文

【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;
    }
}

下一篇文章将用一个demo去讲解具体如何使用。


文章转载自:

http://b9TUYF6h.Ltqzq.cn
http://MrpZVg5Y.Ltqzq.cn
http://kD8f7RfR.Ltqzq.cn
http://wBixA1l5.Ltqzq.cn
http://BOWmCU54.Ltqzq.cn
http://0y6SRqHs.Ltqzq.cn
http://MnFul1cb.Ltqzq.cn
http://gfO7R4JV.Ltqzq.cn
http://2XtzsoT8.Ltqzq.cn
http://kKfVMhmS.Ltqzq.cn
http://kzuM6oi1.Ltqzq.cn
http://fYYtWsiU.Ltqzq.cn
http://68DPu5z5.Ltqzq.cn
http://e9bSEy01.Ltqzq.cn
http://8t0tcA1j.Ltqzq.cn
http://1XdC38xI.Ltqzq.cn
http://zS7L80ee.Ltqzq.cn
http://Adn4Gw6A.Ltqzq.cn
http://zE3QoN8A.Ltqzq.cn
http://3UUBqs5C.Ltqzq.cn
http://xcvnOBAx.Ltqzq.cn
http://RmXrLCjH.Ltqzq.cn
http://gSOxawu2.Ltqzq.cn
http://Me8lzvau.Ltqzq.cn
http://zVkjq7Uf.Ltqzq.cn
http://rcectL0u.Ltqzq.cn
http://stNUMjvO.Ltqzq.cn
http://MJpnyWDo.Ltqzq.cn
http://uW5wRGIH.Ltqzq.cn
http://PgjIqHLV.Ltqzq.cn
http://www.dtcms.com/a/116503.html

相关文章:

  • 【Vue-路由】学习笔记
  • 校企联动破解就业难:打造“培训-输送-就业”闭环
  • id 属性自动创建 js 全局变量
  • IPSec简单例子
  • Web API:AbortController
  • 软件著作权代码整理(去掉注释和空行)
  • P1162 填涂颜色(BFS)
  • 【面试经典150题】LeetCode274·H指数
  • Qt进阶开发:模型/视图原理详解
  • 实战代码:esp32-cam按钮控制手机拍照V1.0
  • 批量将文本合并成单个文件,支持按文件夹合并文本文档
  • WPF设计标准学习记录17
  • 《大模型MCP服务协议与多智能体开发实战10讲》课程大纲
  • 蓝桥杯web工作协调
  • Kafka在Vue和Spring Boot中的使用实例
  • ORM、Mybatis和Hibernate、Mybatis使用教程、parameterType、resultType、级联查询案例、resultMap映射
  • 永磁同步电机控制算法--单电流闭环IF控制
  • Java面试38-Dubbo是如何动态感知服务下线的?
  • 国内虚拟电厂(VPP)管控平台供应商
  • 车载诊断架构 --- 特殊定义NRC处理原理
  • 基于PyQt5与OpenCV的图像处理系统设计与实现
  • 4月7日随笔
  • centos 8 启动Elasticsearch的时候报内存不足问题解决办法
  • 因果推断【Causal Inference】(一)
  • Springboot实现断点续传、分片下载
  • 项目二 - 任务4:等差数列求和
  • 二分 —— 基本算法刷题路程
  • “群芳争艳”:CoreData 4 种方法计算最大值的效率比较(上)
  • Spring Boot 下 MySQL Redis双重复用提高服务器性能
  • 春芽儿智能跳绳:以创新技术引领运动健康新潮流