AOP通知类型

本文详细介绍了Spring AOP中的各种通知类型,包括前置通知(@Before),后置通知(@After),环绕通知(@Around),异常通知(@AfterThrowing)和返回通知(@AfterReturning),并通过实例展示了它们在实际业务中的应用场景和执行顺序。

    前置通知:@Before,在连接点方法执行之前执行。
    后置通知:@After,在连接点方法执行之后,无论如何都会执行。
    环绕通知:@Around,在连接点方法执行之前和之后执行。连接点发生异常时,之后不执行。
    异常通知:@AfterThrowing,在连接点方法发生异常之后执行。
    返回通知:@AfterReturning,在连接点方法返回结果后执行。如果发生异常,则不会执行。

1、pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.0.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.2</version>
    </dependency>
    <dependency>
        <groupId>javax.inject</groupId>
        <artifactId>javax.inject</artifactId>
        <version>1</version>
    </dependency>
</dependencies>

2、业务类

public class UserService {
    public int addUser(String name) {
//        System.out.println(5/0);
        System.out.println("新增用户");
        return 1;
    }
}

3、切面类

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
class UserAspects {
    @Pointcut("execution(public int com.it.huaxin.aop.UserService.addUser(..))")
    public void pointCut(){};

    @Before("pointCut()")
    public void userBefore() {
        System.out.println("@Before,前置通知");
    }

    @After("pointCut()")
    public void userAfter () {
        System.out.println("@After,后置通知");
    }

    @Around("pointCut()")
    public Object userAround (ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("@Around,环绕通知,执行方法之前");
        Object proceed = proceedingJoinPoint.proceed(new Object[]{"张三"});
        System.out.println("@Around,环绕通知,执行方法之后");
        return proceed;
    }

    @AfterThrowing("pointCut()")
    public void userThrowing () {
        System.out.println("@AfterThrowing,异常通知,方法发生异常之后执行");
    }

    @AfterReturning("pointCut()")
    public void userReturing() {
        System.out.println("@AfterReturning,返回通知 ");
    }
}

4、配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
    @Bean
    public UserService userService() {
        return new UserService();
    }

    @Bean
    public UserAspects userAspects() {
        return new UserAspects();
    }
}

5、测试类

import com.it.huaxin.aop.AopConfig;
import com.it.huaxin.aop.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AopTest {
    public static void main(String [] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
        UserService bean = context.getBean(UserService.class);
        bean.addUser("张三");
    }
}

//结果:

@Around,环绕通知,执行方法之前
@Before,前置通知
新增用户
@Around,环绕通知,执行方法之后
@After,后置通知
@AfterReturning,返回通知 

// 发生异常,结果:

@Around,环绕通知,执行方法之前
@Before,前置通知
@After,后置通知
@AfterThrowing,异常通知,方法发生异常之后执行
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.it.huaxin.aop.UserService.addUser(UserService.java:5)
    at com.it.huaxin.aop.UserService$$FastClassBySpringCGLIB$$c2371e8f.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:100)
    at com.it.huaxin.aop.UserAspects.userAround(UserAspects.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at com.it.huaxin.aop.UserService$$EnhancerBySpringCGLIB$$fcde3768.addUser(<generated>)
    at com.it.huaxin.test.AopTest.main(AopTest.java:11)

### AOP通知类型及其适用场景 面向切面编程(AOP)的核心概念之一是通知(Advice),它是增强或改变业务逻辑行为的方式。常见的AOP通知类型包括前置通知、后置通知、环绕通知、异常抛出通知和最终通知[^1]。 - **前置通知(Before Advice)** 在目标方法执行之前运行的通知,主要用于验证输入参数或者记录日志等操作。例如,在接口调用前校验客户端IP是否在白名单中[^2]。 - **后置通知(After Returning Advice)** 当目标方法成功完成后触发的通知,可用于处理返回值的转换或者清理资源等工作。比如对敏感数据进行脱敏处理后再返回给前端[^3]。 - **环绕通知(Around Advice)** 这是最强大的一种通知形式,它可以完全控制目标方法的执行流程,甚至可以选择根本不调用原方法。适合用于性能监控、事务管理等功能实现。 - **异常抛出通知(After Throwing Advice)** 只有当被代理的方法抛出了指定类型的异常时才会被执行的一种特殊形式的事后通知。常用来捕获错误信息并向运维团队发送告警邮件。 - **最终通知(After (Finally) Advice)** 不管目标方法是以正常结束还是因为发生未被捕获的例外情况而终止都会执行此类通知。典型用途如关闭数据库连接池之类的收尾工作。 ### 面向上线接口且减少修改源码风险的设计模式 考虑到直接改动生产环境下的代码可能带来未知隐患,因此建议采取如下几种策略来规避潜在问题: #### 使用装饰者模式 装饰者模式允许开发者通过创建一个新的对象——即所谓的“装饰”,围绕现有的对象增加额外的行为,而不是去修改原来的类文件本身。这样做的好处在于保留了原有的功能不变的同时还能灵活添加新的特性[^4]。 #### 利用组合模式替代继承关系 相比于传统的单根继承体系容易造成刚性耦合的问题,运用组合模式可以让各个组件之间更加松散地联系起来。正如前面提到过的集合框架内部构造不可变视图那样巧妙的做法一样,我们也可以模仿类似的机制达到目的[^5]。 ```java // 示例:使用组合模式构建安全过滤链 public abstract class Filter { protected Filter nextFilter; public void setNext(Filter filter){ this.nextFilter = filter; } public abstract boolean doFilter(Request request, Response response); } public class AuthFilter extends Filter{ @Override public boolean doFilter(Request reqeust ,Response respose ){ // 实现认证逻辑... if(nextFilter != null && isAuthenticated()){ return nextFilter.doFilter(reqeust,respose ); }else{ return false ; } } } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青春1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值