当前位置: 首页 > 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去讲解具体如何使用。

相关文章:

  • 【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处理原理
  • 校园网共青团网站建设方案/苏州手机关键词优化
  • 福建建设培训中心网站/免费自助建站模板
  • 网站制作怎样盈利/多层次网络营销合法吗
  • 公司网站制作的费用申请书/镇江seo
  • 淮北市11月30日疫情/什么建站程序最利于seo
  • 那些门户网站的官网做的好/网络宣传平台有哪些