SpringAOP

一、AOP介绍

AOP(面向切面编程)是一种编程思想,底层逻辑是动态代理。什么是动态代理呢?动态代理就是不改变源码的情况下,对目标方法进行增强。传统的动态代理太过繁琐,因此SpringAOP对其进行了一系列简化,使得原本繁琐的代码变得精简,同时使用也更加灵活。

二、AOP使用案例

在开发过程中,日志是必不可少的。以前的日志代码需要在每个方法上都添加相同的一段代码,这导致代码复用性很低。

SpringAOP将这都进行了优化,以下是二者代码的区别:

传统的日志功能:
public class MyClass {     

private static final Logger logger = LogManager.getLogger(MyClass.class);    

 public void doSomethingWithLogging(String input) {        
// 记录方法开始的日志       
logger.info("Method 'doSomethingWithLogging' started with input: {}", input); 

try {// 执行具体的业务逻辑            
     // ...        
     
// 记录方法成功结束的日志            
logger.info("Method 'doSomethingWithLogging' successfully completed");   
     
} catch (Exception e) {      
      
// 记录方法异常的日志            
logger.error("An error occurred in method 'doSomethingWithLogging'", e);       
   }   
  } 
}

SpringAOP日志功能:
@Aspect 
@Component 
public class LoggingAspect {     
private Log logger = LogFactory.getLog(this.getClass());   
 
@Before("execution(* com.example.MyService.*(..))") //前置通知
public void logBefore(JoinPoint joinPoint) {        
      logger.info("Method " + joinPoint.getSignature().getName() + " is about to be executed");    }     

@AfterReturning(pointcut = "execution(* com.example.MyService.*(..))", returning = "result")//运行成功后通知
public void logAfterReturning(JoinPoint joinPoint, Object result) {        
      logger.info("Method " + joinPoint.getSignature().getName() + " executed successfully");    }  
   
@AfterThrowing(pointcut = "execution(* com.example.MyService.*(..))", throwing = "exception")//运行异常通知
public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {        
      logger.error("Exception thrown from method " + joinPoint.getSignature().getName() + ": " + exception.getMessage());    
  } 
}
@Service 
public class MyService {        
    public void doSomething() {        
        // 具体业务逻辑    
  } 
}

在这个示例中,LoggingAspect类是一个切面,它定义了在MyService类中的方法执行前、执行后(成功返回)和执行后(抛出异常)分别记录日志的逻辑。当MyService类中的方法被调用时,LoggingAspect中对应的通知将会被触发,实现日志记录的功能。

三、SpringAOP

简介

SpringAOP是对AOP思想的一种实现,Spring底层同时支持jdk动态代理(基于接口)和cglib动态代理(基于继承)。Spring会根据被代理的类是否有接口自动选择代理方式

如果有接口,就采用jdk动态代理

如果没接口,就采用cglib的方式

核心概念

  • 目标对象(Target)
    被代理的对象

  • 连接点(JoinPoint)
    目标对象中的所有方法

  • 切入点(PointCut)
    目标对象中要真正进行功能增强的方法

    切入点表达式:
    1、指定匹配切入点的规则:*用于返回值,包名,方法名,表示任意,占一个位置,.. 表示0-n的任意数量
    2、execution表达式匹配

@Pointcut("execution(* com.example.service.*.*(..))") 
private void serviceMethods() {

}

3、@annotation注解匹配

自定义一个注解,把它标记在对应的方法上,通过切点表达式去识别这个注解
@Pointcut("@annotation(com.example.annotation.Loggable)") 
private void loggableMethods() {
}	

* **增强 (Advice 通知)** 一个具体增强功能(增强对象 增强方法)

前置通知(before):增强方法在切点运行之前执行

返回通知(after-returning):增强方法在切点正常完成后执行的通知,不包括抛出异常的情况

异常通知(after-throwing):增强方法在某切点抛出异常退出时执行的通知

后置通知(after):增强方法在某切点退出的时候执行的通知(不论是正常返回还是异常退出)
环绕通知(around):一种特殊的通知,他允许以编码的形式实现上面的四大通知

  • 切面 (Aspect)
    切面是一种描述,描述的是: 哪个增强方法加入到了哪个切点的什么位置
    总之切面可以理解为 切入点和增强的结合

@Aspect 
@Component 
public class LoggingAspect {     
@Around("execution(* com.example.MyService.*(..))")    
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {        
// 在方法执行前记录日志
System.out.println("Before method execution: " + joinPoint.getSignature().getName()); 
// 执行目标方法
Object result = joinPoint.proceed();         
// 在方法执行后记录日志        
System.out.println("After method execution: " + joinPoint.getSignature().getName());         
return result;    
  } 
}

在这个示例中,LoggingAspect类是一个切面,它定义了一个环绕通知。在logAround方法中,我们可以在目标方法执行前和执行后分别记录日志,并通过调用joinPoint.proceed()来执行目标方法。

然后,在你的Service类中,定义一个方法,该方法将被切面所通知:

@Service public class MyService {        
public void doSomething() {        
// 具体业务逻辑    
  } 
}
posted @   海a  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示