Spring的AOP的通知类型(九)

Spring中的通知类型

通知类型,是按照在目标方法的前后顺序来决定的,比如在目标方法前或者后面执行,同时还需要在配置文件XML中进行各项通知的配置,通过aop:config 标签实现。

先在配置文件中配置好相应的切入点(pointcut),也就是配置目标方法

    <!--配置代理,通过AOP的配置完成对目标类产生代理-->
    <aop:config>
        <!--通过表达式配置哪些类的哪些方法需要进行增强-->
        <!--也就是配置切入点-->
        <!--  * 代表任意返回值-->
        <!--  .. 代表任意参数-->
        <aop:pointcut id="pointcut1" expression="execution(* SpringAopdemo.ProductDaoImpl.save(..))"/>
        <aop:pointcut id="pointcut2" expression="execution(* SpringAopdemo.ProductDaoImpl.del(..))"/>
        <aop:pointcut id="pointcut3" expression="execution(* SpringAopdemo.ProductDaoImpl.update(..))"/>
        <aop:pointcut id="pointcut4" expression="execution(* SpringAopdemo.ProductDaoImpl.find(..))"/>
    </aop:config>

所有的通知都必须配置在 aop:aspect 标签中,处于 aop:config 标签内,用ref = “目标方法类名”的方式,指定目标方法存放的类,使用pointcut-ref 标签用来指定配置好的切入点。

  • 前置通知(能够获取切入点(JoinPoint)信息,其实每个通知都能获取切入点信息,如方法名,参数等)(标签:aop:before)

    在目标方法之前进行操作,可以用来校验权限操作等

XML前置通知配置:

<!--配置切面-->
<!--配置通知和指定切入点-->

<!--指定切面类,也就是增强方法的类-->
<aop:aspect ref="myAspect">
    <!--配置通知(增强方法),和指定的切入点(目标方法,也就是save方法)-->
    <!--前置通知 能够获得切入点信息-->
    <aop:before method="checkPri" pointcut-ref="pointcut1"></aop:before>
</aop:aspect>

增强方法 checkPri:

//    前置通知,能够获得切入点信息
// 通过JoinPoint类 获得目标方法
public void checkPri(JoinPoint joinPoint){
    System.out.println("权限校验========"  + joinPoint);
}
  • 后置通知(能够获取切入点(JoinPoint)信息和目标方法返回值(Object result),一般可以用来记录操作日志)(标签:after-returning)

XML配置:

<!--后置通知,能够获得切入点信息和目标方法返回值,需要配置 returning 参数名字-->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"></aop:after-returning>

需要注意的是,增强方法 writeLog 中定义的返回值参数,需要和 returning 定义的参数名一致。

增强方法 writeLog:

//    后置通知,能够获取切入点信息和返回值
public void writeLog(JoinPoint joinPoint,Object result){
    System.out.println("记录日志========" + joinPoint +"===" + result);
}
  • 环绕通知(功能最强的一个通知,因为它可以阻止目标方法的运行,因为环绕通知执行在目标方法前后。可以用作运行时间性能监控)(通过ProceedingJoinPoint类的proceed()方法来执行目标方法)(标签:aop:around)

XML配置:

<!--环绕通知-->
<aop:around method="around" pointcut-ref="pointcut3"/>

around 增强方法:

//    环绕通知,
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("环绕前通知========");
    //通过ProceedingJoinPoint 的 proceed 方法 执行目标方法,如果不执行就可以阻止目标方法执行。
    //由于目标方法可能存在返回值,所以需要返回一个object对象
    Object object = joinPoint.proceed();
    System.out.println("环绕后通知========");
    return object;
}
  • 异常抛出通知(能够获取到异常信息)(在目标方法有异常抛出的时候,才会执行,可以用于事务管理,当事务中抛出错误,可以执行回滚)(标签:aop:after-throwing)

XML配置:

<!--异常通知,当目标方法抛出异常的时候执行,能够获取到异常信息-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>

需要注意的是,afterThrowing 增强方法中传入的参数需要和throwing属性定义的名称 “ex” 一致

afterThrowing 增强方法

//    异常抛出通知,能获取到异常通知信息
public void afterThrowing(Throwable ex){
	//使用getMessage() 方法获取异常信息
    System.out.println("抛出异常========" + ex.getMessage());
}
  • 最终通知(相当于finally代码块中内容,最后总是会执行,无论有无异常)(标签:aop:after)

XML配置:

 <!--最终通知,总是会被执行,无论有无异常-->
 <aop:after method="after" pointcut-ref="pointcut4"/>

after 增强方法:

//    最终通知:相当于finally代码块中内容,最后总是会执行
public void after() {
    System.out.println("最终通知========");
}
  • 引介通知

完整的applicationContext.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--Spring的注解开发:组件扫描,扫描需要使用注解的类包(类上注解:可以直接使用属性注入的注解)-->
    <!--扫描是为扫描类上的注解-->
    <!--<context:component-scan base-package="SpringAopdemo"/>-->

    <bean id="ProductDao" class="SpringAopdemo.ProductDaoImpl"/>
    <bean id="myAspect" class="SpringAopdemo.MyAspectXML"/>

    <!--配置代理,通过AOP的配置完成对目标类产生代理-->
    <aop:config>
        <!--通过表达式配置哪些类的哪些方法需要进行增强-->
        <!--也就是配置切入点-->
        <!--  * 代表任意返回值-->
        <!--  .. 代表任意参数-->
        <aop:pointcut id="pointcut1" expression="execution(* SpringAopdemo.ProductDaoImpl.save(..))"/>
        <aop:pointcut id="pointcut2" expression="execution(* SpringAopdemo.ProductDaoImpl.del(..))"/>
        <aop:pointcut id="pointcut3" expression="execution(* SpringAopdemo.ProductDaoImpl.update(..))"/>
        <aop:pointcut id="pointcut4" expression="execution(* SpringAopdemo.ProductDaoImpl.find(..))"/>
        <!--配置切面-->
        <!--配置通知和指定切入点-->

        <!--指定切面类,也就是增强方法的类-->
        <aop:aspect ref="myAspect">
            <!--配置通知(增强方法),和指定的切入点(被增强的方法,也就是save方法)-->
            <!--前置通知 能够获得切入点信息-->
            <aop:before method="checkPri" pointcut-ref="pointcut1"></aop:before>
            <!--后置通知,能够获得切入点信息和目标方法返回值,需要配置 returning 参数名字-->
            <aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"></aop:after-returning>
            <!--环绕通知-->
            <aop:around method="around" pointcut-ref="pointcut3"/>
            <!--异常通知,当目标方法抛出异常的时候执行,能够获取到异常信息-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
            <!--最终通知,总是会被执行,无论有无异常-->
            <aop:after method="after" pointcut-ref="pointcut4"/>
        </aop:aspect>
    </aop:config>
</beans>
### Spring AOP 通知类型及其执行顺序与优先级 Spring AOP 的核心在于通过不同的通知类型(Advice Types)来增强目标方法的功能。以下是关于不同类型通知的执行顺序以及其优先级的相关说明。 #### 不同通知类型的定义 Spring 支持五种主要的通知类型,每种类型都有特定的作用范围和触发时机: - **前置通知(Before Advice)**: 在目标方法调用前执行[^4]。 - **后置通知(After Advice)**: 在目标方法完成后执行,无论是否有异常发生。 - **返回通知(After Returning Advice)**: 当目标方法成功执行并返回结果时触发。 - **异常通知(After Throwing Advice)**: 只有当目标方法抛出指定异常时才会触发。 - **环绕通知(Around Advice)**: 是最强大的一种通知形式,它可以在目标方法前后都执行逻辑,并能够控制是否继续执行目标方法。 #### 执行顺序分析 在实际运行过程中,如果一个切入点被多个切面拦截,则这些切面会被按一定规则排序形成一条调用链。具体来说: 1. 进入切入点时,具有较高优先级的切面中的前置通知会率先被执行; 2. 如果存在环绕通知,它的 `proceed()` 方法决定了何时真正调用目标方法或者后续其他低优先级的通知; 3. 离开切入点时,高优先级的后置/返回/异常通知则会在较低优先级之后才得以处理[^1]。 #### 切面优先级机制 为了决定各个切面之间的相对位置关系,Spring 提供了一套完善的优先级判定体系。通常情况下,默认不设置任何特殊属性的话,各切面之间视为平等对待;然而可以通过实现 Ordered 接口或利用 @Order 注解显式声明各自的次序级别[^2]。数值越小代表优先度越高,意味着更早介入到整个事务链条当中去。 #### 示例代码展示 下面给出一段简单的 Java 配置类用于演示如何配置多种类型通知: ```java @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint){ System.out.println("Logging before method: "+joinPoint.getSignature().getName()); } @AfterReturning(pointcut="execution(* com.example.service.*.*(..))", returning="result") public void logAfterReturn(Object result){ System.out.println("Method returned value :"+result); } @AfterThrowing(pointcut="execution(* com.example.service.*.*(..))", throwing="error") public void logAfterError(Exception error){ System.out.println("Exception caught:"+error.getMessage()); } } ``` 上述例子展示了基本的日志记录方面,其中包含了 Before 和 After 类型通知实例化过程[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值