Spring中AOP的通知方式

一、案例搭建

1、pom.xml

		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

2、IAccountService.java

public interface IAccountService {
    /**
     * 模拟保存账户
     */
    void saveAccount();

    /**
     * 模拟更新账户
     * @param i
     */
    void updateAccount(int i);

    /**
     * 模拟删除账户
     * @return
     */
    int deleteAccount();
}

3、AccountServiceImpl.java

public class AccountServiceImpl implements IAccountService {
    public void saveAccount() {
        System.out.println("执行了保存");
        //int i = 1/0;
    }

    public void updateAccount(int i) {
        System.out.println("执行了更新" + i);
    }

    public int deleteAccount() {
        System.out.println("执行了删除");
        return 0;
    }
}

4、Logger.java

public class Logger {
    /**
     * 前置通知
     */
    public void beforePrintLog() {
        System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了......");
    }
    /**
     * 后置通知
     */
    public void afterPrintLog() {
        System.out.println("后置通知Logger类中的afterPrintLog方法开始记录日志了......");
    }
    /**
     * 异常通知
     */
    public void throwingPrintLog() {
        System.out.println("异常通知Logger类中的throwingPrintLog方法开始记录日志了......");
    }
    /**
     * 最终通知
     */
    public void finalPrintLog() {
        System.out.println("最终通知Logger类中的finalPrintLog方法开始记录日志了......");
    }
    /**
     * 环绕通知
     */
    public Object aroundPrintLog(ProceedingJoinPoint pjp) {
        Object rtValue = null;
        try {
            // 得到方法执行所需的参数
            Object[] args = pjp.getArgs();
            System.out.println("Logger类中的aroundPrintLog方法开始记录日志了......前置");

            // 明确调用业务层方法
            rtValue= pjp.proceed(args);

            System.out.println("Logger类中的aroundPrintLog方法开始记录日志了......后置");
            return rtValue;
        } catch (Throwable t) {
            System.out.println("Logger类中的aroundPrintLog方法开始记录日志了......异常");
            throw new RuntimeException(t);
        } finally {
            System.out.println("Logger类中的aroundPrintLog方法开始记录日志了......最终");
        }

    }
}

5、bean.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置Spring的IoC,把accountService对象注入到容器中-->
    <bean id="accountService" class="com.uos.service.impl.AccountServiceImpl"></bean>

    <!--通知bean-->
    <bean id="logger" class="com.uos.utils.Logger"></bean>
    <aop:config>
        <!--全局配置切入点表达式,注意需要在aop:config标签内部编写,并注意顺序-->
        <aop:pointcut id="pt1" expression="execution(* com.uos.service.impl.*.*(..))"/>
        <!--配置切面-->
        <aop:aspect id="logAdvice" ref="logger">
            <!--注意:后置通知和异常通知只能执行其中一个-->
            <!--配置前置通知:在切入点方法之前执行-->
            <!--<aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>-->
            <!--配置后置通知:在切入点方法正常执行之后-->
            <!--<aop:after-returning method="afterPrintLog" pointcut-ref="pt1"></aop:after-returning>-->
            <!--配置异常通知:在切入点方法执行产生异常之后执行-->
            <!--<aop:after-throwing method="throwingPrintLog" pointcut-ref="pt1"></aop:after-throwing>-->
            <!--配置最终通知:无论切入点方法是否能被正常之后都会执行-->
            <!--<aop:after method="finalPrintLog" pointcut-ref="pt1"></aop:after>-->
            <!--配置通用切入点表达式 id属性唯一标识一个切入点,expression属性是表达式的内容-->
            <!--<aop:pointcut id="pt1" expression="execution(* com.uos.service.impl.*.*(..))"/>-->
            <aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>
        </aop:aspect>
    </aop:config>
</beans>

6、AopTest.java

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService accountService = (IAccountService) applicationContext.getBean("accountService");
        accountService.saveAccount();
    }
}

二、通知方式

在这里,我们先配置好全局的切入点表达式,之后引用即可。

<!--全局配置切入点表达式,注意需要在aop:config标签内部编写-->
<aop:pointcut id="pt1" expression="execution(* com.uos.service.impl.*.*(..))"/>

1、前置通知

配置前置通知:在切入点方法之前执行。

<aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>

2、后置通知

配置后置通知:在切入点方法正常执行之后。

<aop:after-returning method="afterPrintLog" pointcut-ref="pt1"></aop:after-returning>

3、异常通知

配置异常通知:在切入点方法执行产生异常之后执行。

<aop:after-throwing method="throwingPrintLog" pointcut-ref="pt1"></aop:after-throwing>

4、最终通知

配置最终通知:无论切入点方法是否能被正常之后都会执行。

<aop:after method="finalPrintLog" pointcut-ref="pt1"></aop:after>

5、环绕通知

配置环绕通知:环绕通知包含了前置通知、后置通知、异常通知和最终通知。

<aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>
原创文章 154 获赞 48 访问量 8535

猜你喜欢

转载自blog.csdn.net/weixin_41842236/article/details/106025580