Spring Aop--通知注解

一、环绕注解

环绕注解

环绕注解@Aroud

注解 描述
@Around @Around是Spring AOP中的一种通知类型,用于在目标方法执行前后进行环绕操作。它可以在方法调用前后增加额外的逻辑,例如日志记录、性能监控等。@Around注解需要配合AspectJ表达式来指定切入点,定义切面类的方法,并在方法内部通过ProceedingJoinPoint参数来控制目标方法的执行流程。

环绕注解,通过环绕注解可以实现对增强的整合。

对于环绕注解需要创建ProceedingJoinPoint对象并需要使用连两个对应方法

方法 描述
proceed() 执行被通知的目标方法,并返回其返回值。在环绕通知中必须调用此方法,否则目标方法不会执行。
getArgs() 获取目标方法的参数值数组。返回的参数数组是Object类型的。

环绕注解使用案例:

java 复制代码
@Component
@Aspect
public class RoundAdvice {

    @Around("com.alphamilk.Advice.MyPointcut.pointcut1()")
    public Object Transation(ProceedingJoinPoint joinPoint){
//        获取方法参数
        Object[] args = joinPoint.getArgs();
//        获取返回值
        Object result = null;

        try {
            System.out.println("事务开始");
//            执行对应方法
           result =  joinPoint.proceed(args);
            System.out.println("事务结束");
        } catch (Throwable e) {
            System.out.println("事务回滚");
            throw new RuntimeException(e);
        }
        return result;
    }
}

注意:使用增强需要开启通知注解

java 复制代码
@ComponentScan(value = "com.alphamilk")
@Configuration
//开启增强注解
@EnableAspectJAutoProxy
public class JavaConfig {
}

而如果不是使用环绕注解,则需要使用@Before @After @AfterReturning等

java 复制代码
@Component
@Aspect
public class advice {
  @Before("com.alphamilk.Advice.MyPointcut.pointcut1()")
    public void Before(JoinPoint joinPoint) {
        System.out.println("事务开始");
    }

 @After("com.alphamilk.Advice.MyPointcut.pointcut1()")
    public void After(JoinPoint joinPoint) {
        System.out.println("事务结束");
    }

    @AfterReturning(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",returning = "result")
    public void AfterReturning(JoinPoint joinPoint,Object result) {
        System.out.println("调用拥有返回值的方法");
    }

    @AfterThrowing(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",throwing = "throwable")
    public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {
        System.out.println("调用有异常的方法");
    }
}

使用环绕注解的优缺点

优点:

  1. 灵活性高:环绕注解提供了最大程度的灵活性,可以在目标方法执行前后插入额外的逻辑代码,对方法的执行过程进行全面控制。
  2. 统一处理:通过环绕注解,可以将通用的逻辑代码抽取到切面中,实现统一的处理逻辑,避免在各个目标方法中重复编写相同的代码。
  3. 可以修改返回值:在环绕通知中,可以通过修改目标方法的返回值来影响最终的结果。

缺点:

  1. 复杂性增加:相对于其他类型的通知,环绕注解的使用稍显复杂,需要更多的理解和掌握,特别是对于ProceedingJoinPoint的使用。
  2. 性能开销:由于环绕注解会包裹整个目标方法的执行流程,在某些情况下可能会带来一定的性能开销,特别是处理逻辑较为复杂的情况。
  3. 可能引入副作用:在环绕通知中对目标方法做任意修改时,需要谨慎操作,避免引入不可预料的副作用,导致程序出现异常或不正常的行为。

二、优先级注解

注解 描述
@Order @Order是Spring框架中用于定义组件的加载顺序的注解。它可以用在类级别或方法级别上。当多个组件都实现了同一个接口或继承了同一个父类时,通过@Order注解可以指定它们的加载顺序。@Order的值越小,优先级越高,具有更高的加载顺序。@Order注解的值可以是任意整数。需要注意的是,相同优先级的组件加载顺序是不确定的,所以最好将优先级设置为不同的值来避免不确定性。

如果对于同一个方法有两种甚至多种增强,并且需要指定增强的循序,则需要使用@Order优先级注解来设置。

对于其使用,核心在于:指定一个优先级,Order的值越低越是优先,越高优先级前置先执行,后置后执行

案例代码:(第一个增强)

java 复制代码
@Component
@Aspect
//设置一个优先级更高注解
@Order(10)
public class advice {
  @Before("com.alphamilk.Advice.MyPointcut.pointcut1()")
    public void Before(JoinPoint joinPoint) {
        System.out.println("优先级高前置执行");
    }

 @After("com.alphamilk.Advice.MyPointcut.pointcut1()")
    public void After(JoinPoint joinPoint) {
        System.out.println("优先级高后置后执行");
    }

    @AfterReturning(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",returning = "result")
    public void AfterReturning(JoinPoint joinPoint,Object result) {
        System.out.println("调用拥有返回值的方法");
    }

    @AfterThrowing(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",throwing = "throwable")
    public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {
        System.out.println("调用有异常的方法");
    }
}

第二个增强

java 复制代码
@Component
@Aspect
@Order(20)
public class RoundAdvice {

    @Around("com.alphamilk.Advice.MyPointcut.pointcut1()")

    public Object Transation(ProceedingJoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        Object result = null;

        try {
            System.out.println("优先级低前置后执行");
//            执行对应方法
           result =  joinPoint.proceed(args);
            System.out.println("优先级低后置先执行");
        } catch (Throwable e) {
            System.out.println("事务回滚");
            throw new RuntimeException(e);
        }
        return result;
    }
}

相关推荐
JH30735 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
2301_818732069 小时前
前端调用控制层接口,进不去,报错415,类型不匹配
java·spring boot·spring·tomcat·intellij-idea
码字的字节9 小时前
Spring Cloud服务注册与发现(一):手把手搭建Eureka Server,详解高可用配置
spring·spring cloud·eureka
大厂资深架构师9 小时前
Spring Cloud Eureka在后端系统中的服务剔除策略
spring·spring cloud·ai·eureka
暮色妖娆丶12 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
7哥♡ۣۖᝰꫛꫀꪝۣℋ14 小时前
微服务负载均衡
spring·微服务
Boop_wu15 小时前
Spring生态
java·后端·spring
清水白石00817 小时前
深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
java·python·spring·缓存
夕除18 小时前
js--15
java·jvm·spring