• Spring的前置增强,后置增强,异常抛出增强、自定义增强


    前言

            根据b站up主的视频,进行编码总结。

            就我自己的理解,切点表示的是在程序运行中,在何处切入想要执行的逻辑代码,即表示需要增强的部分,通常情况下,使用明确的类名和方法名称,或者正则表达式指定这些切入点。

            整体的目录结构:

    目录

    前言

    1、先创建一个maven项目,pom文件中引入相关的依赖

    2、在resources目录下创建一个spring-aop.xml文件

    3、在java文件下创建advice包以及该包下相应的类

     4、后置增强

     5、异常抛出增强

    6、环绕增强

    7、最终增强(即实现了后置增强和异常抛出增强)

    8、自定义增强

    9、总结


    1、先创建一个maven项目,pom文件中引入相关的依赖

    1. <dependency>
    2. <groupId>junitgroupId>
    3. <artifactId>junitartifactId>
    4. <version>4.12version>
    5. <scope>testscope>
    6. dependency>
    7. <dependency>
    8. <groupId>org.springframeworkgroupId>
    9. <artifactId>spring-contextartifactId>
    10. <version>5.3.22version>
    11. dependency>
    12. <dependency>
    13. <groupId>org.aspectjgroupId>
    14. <artifactId>aspectjweaverartifactId>
    15. <version>1.9.2version>
    16. dependency>

    2、在resources目录下创建一个spring-aop.xml文件

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean class="advice.AdviceTarget" id="adviceTarget"/>
    10. <bean class="advice.BeforeService" id="beforeService"/>
    11. <bean class="advice.AfterReturnService" id="afterReturnService"/>
    12. <bean class="advice.ExceptionService" id="exceptionService"/>
    13. <bean class="advice.AroundService" id="aroundService"/>
    14. <bean class="advice.AfterService" id="afterService"/>
    15. <bean class="advice.AdviceTest" id="adviceTest"/>
    16. <aop:config>
    17. <aop:pointcut id="point" expression="execution(* advice.AdviceTarget.*(..))"/>
    18. <aop:aspect ref="adviceTest">
    19. <aop:before method="test" pointcut-ref="point"/>
    20. aop:aspect>
    21. aop:config>
    22. beans>

            要使用到的类都要在此xml文件中进行bean文件的配置(spring的任何从操作都离不开bean)

    3、在java文件下创建advice包以及该包下相应的类

            前置增强  BeforeService.java

    1. package advice;
    2. import org.springframework.aop.MethodBeforeAdvice;
    3. import java.lang.reflect.Method;
    4. import java.util.Arrays;
    5. /**
    6. * @Author 不要有情绪的 ljy
    7. * @Date 2022/9/7 17:33
    8. * @Description:
    9. */
    10. public class BeforeService implements MethodBeforeAdvice {
    11. public void before(Method method, Object[] args, Object target) throws Throwable {
    12. System.out.println("---------------前置增强start---------");
    13. System.out.println(target + "的" + method.getName() + "方法,参数是" + Arrays.toString(args));
    14. System.out.println("---------------前置增强end---------");
    15. }
    16. }

            在test下的springTest包下编写测试类AdviceTest:

    1. package springTest;
    2. import advice.AdviceTarget;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. /**
    5. * @Author 不要有情绪的 ljy
    6. * @Date 2022/9/7 18:11
    7. * @Description:
    8. */
    9. public class AdviceTest {
    10. public static void main(String[] args) {
    11. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
    12. AdviceTarget target = context.getBean(AdviceTarget.class);
    13. target.testAdvice("p1", 123);
    14. // try {
    15. // target.testException();
    16. // } catch (Exception e) {
    17. // e.printStackTrace();
    18. // }
    19. }
    20. }

    在spring-aop.xml文件中创建bean,并配置切点(当前为前置增强)

    1. <bean class="advice.AdviceTarget" id="adviceTarget"/>
    2. <bean class="advice.BeforeService" id="beforeService"/>
    3. <aop:config>
    4. <aop:pointcut id="point" expression="execution(* advice.AdviceTarget.*(..))"/>
    5. <aop:advisor advice-ref="beforeService" pointcut-ref="point"/>
    6. aop:config>

    对以上配置文件进行解释,首先使用标签声明两个类,然后配置切入点aop:pointcut,切入点为advice包下的AdviceTarget类下的所有方法,aop:advisor表示要切入的类。

    运行结果:

     4、后置增强

    1. package advice;
    2. import org.springframework.aop.AfterReturningAdvice;
    3. import java.lang.reflect.Method;
    4. import java.util.Arrays;
    5. /**
    6. * @Author 不要有情绪的 ljy
    7. * @Date 2022/9/7 20:21
    8. * @Description: 后置增强必须是正常执行完的代码,如果程序执行报错,那么不会进行后置增强
    9. */
    10. public class AfterReturnService implements AfterReturningAdvice {
    11. public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    12. System.out.println("---------------后置增强start---------");
    13. System.out.println(target + "的" + method.getName() + "方法,参数是" + Arrays.toString(args)+" 返回值是: "+returnValue);
    14. System.out.println("---------------后置增强end---------");
    15. }
    16. }
    1. <bean class="advice.AdviceTarget" id="adviceTarget"/>
    2. <bean class="advice.AfterReturnService" id="afterReturnService"/>
    3. <aop:config>
    4. <aop:pointcut id="point" expression="execution(* advice.AdviceTarget.*(..))"/>
    5. <aop:advisor advice-ref="afterReturnService" pointcut-ref="point"/>
    6. aop:config>

    运行结果:

     5、异常抛出增强

    1. package advice;
    2. import org.springframework.aop.ThrowsAdvice;
    3. import java.lang.reflect.Method;
    4. import java.util.Arrays;
    5. /**
    6. * @Author 不要有情绪的 ljy
    7. * @Date 2022/9/7 20:33
    8. * @Description: 异常抛出增强是为了解决后置增强抛出异常不能正常进行的问题
    9. * 那么异常抛出增强可用于数据库提交过程中的数据回滚,能够保证数据的一致性
    10. */
    11. public class ExceptionService implements ThrowsAdvice {
    12. public void afterThrowing(Method method, Object[] args, Object target, Exception e) {
    13. System.out.println("---------------异常抛出增强start---------");
    14. System.out.println(target + "的" + method.getName() + "异常信息是:" + e.getMessage());
    15. System.out.println("---------------异常抛出增强end---------");
    16. }
    17. }
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean class="advice.AdviceTarget" id="adviceTarget"/>
    10. <bean class="advice.BeforeService" id="beforeService"/>
    11. <bean class="advice.AfterReturnService" id="afterReturnService"/>
    12. <bean class="advice.ExceptionService" id="exceptionService"/>
    13. <bean class="advice.AroundService" id="aroundService"/>
    14. <bean class="advice.AfterService" id="afterService"/>
    15. <bean class="advice.AdviceTest" id="adviceTest"/>
    16. <aop:config>
    17. <aop:pointcut id="point" expression="execution(* advice.AdviceTarget.*(..))"/>
    18. <aop:advisor advice-ref="exceptionService" pointcut-ref="point"/>
    19. aop:config>
    20. beans>

    这个时候就要打开测试异常的方法,

    AdviceTest.java
    1. package springTest;
    2. import advice.AdviceTarget;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. /**
    5. * @Author 不要有情绪的 ljy
    6. * @Date 2022/9/7 18:11
    7. * @Description:
    8. */
    9. public class AdviceTest {
    10. public static void main(String[] args) {
    11. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
    12. AdviceTarget target = context.getBean(AdviceTarget.class);
    13. // target.testAdvice("p1", 123);
    14. try {
    15. target.testException();
    16. } catch (Exception e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. }

    运行结果:

            异常抛出增强是为了解决后置增强在执行过程中抛出异常,而不执行的情况,例如:在一个数据事务提交过程中,由于出现异常,导致数据不会滚,即后置增强不能正常运行,那么异常抛出增强就可以实现数据的回滚。

    6、环绕增强

    1. package advice;
    2. import org.aopalliance.intercept.MethodInterceptor;
    3. import org.aopalliance.intercept.MethodInvocation;
    4. import java.lang.reflect.Method;
    5. import java.util.Arrays;
    6. /**
    7. * @Author 不要有情绪的 ljy
    8. * @Date 2022/9/8 9:21
    9. * @Description:
    10. */
    11. public class AroundService implements MethodInterceptor {
    12. public Object invoke(MethodInvocation invocation) throws Throwable {
    13. System.out.println("--------环绕增强Start----------");
    14. Object target = invocation.getThis(); //目标方法所在的类
    15. Method method = invocation.getMethod(); //被调用的目标方法
    16. Object[] args = invocation.getArguments(); //调用目标方法时的参数
    17. System.out.println(target + " 的 " + method.getName() + " 方法。参数是: " + Arrays.toString(args));
    18. try {
    19. Object returnVal = invocation.proceed(); //执行目标方法
    20. System.out.println("--------环绕增强End----------");
    21. return returnVal;
    22. } catch (Exception e) {
    23. System.out.println("--------环绕增强捕获异常----------");
    24. throw e;
    25. }
    26. }
    27. }
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean class="advice.AdviceTarget" id="adviceTarget"/>
    10. <bean class="advice.BeforeService" id="beforeService"/>
    11. <bean class="advice.AfterReturnService" id="afterReturnService"/>
    12. <bean class="advice.ExceptionService" id="exceptionService"/>
    13. <bean class="advice.AroundService" id="aroundService"/>
    14. <bean class="advice.AfterService" id="afterService"/>
    15. <bean class="advice.AdviceTest" id="adviceTest"/>
    16. <aop:config>
    17. <aop:pointcut id="point" expression="execution(* advice.AdviceTarget.*(..))"/>
    18. <aop:advisor advice-ref="aroundService" pointcut-ref="point"/>
    19. aop:config>
    20. beans>

    带异常的执行结果:(不执行环绕增强end)

    7、最终增强(即实现了后置增强和异常抛出增强)

    1. package advice;
    2. import org.springframework.aop.AfterReturningAdvice;
    3. import org.springframework.aop.ThrowsAdvice;
    4. import java.lang.reflect.Method;
    5. import java.util.Arrays;
    6. /**
    7. * @Author 不要有情绪的 ljy
    8. * @Date 2022/9/8 9:34
    9. * @Description:
    10. */
    11. public class AfterService implements AfterReturningAdvice, ThrowsAdvice {
    12. @Override
    13. public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    14. System.out.println("---------------后置增强start---------");
    15. System.out.println(target + "的" + method.getName() + "方法,参数是" + Arrays.toString(args) + " 返回值是: " + returnValue);
    16. System.out.println("---------------后置增强end---------");
    17. }
    18. public void afterThrowing(Method method, Object[] args, Object target, Exception e) {
    19. System.out.println("---------------异常抛出增强start---------");
    20. System.out.println(target + "的" + method.getName() + "异常信息是:" + e.getMessage());
    21. System.out.println("---------------异常抛出增强end---------");
    22. }
    23. }
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean class="advice.AdviceTarget" id="adviceTarget"/>
    10. <bean class="advice.BeforeService" id="beforeService"/>
    11. <bean class="advice.AfterReturnService" id="afterReturnService"/>
    12. <bean class="advice.ExceptionService" id="exceptionService"/>
    13. <bean class="advice.AroundService" id="aroundService"/>
    14. <bean class="advice.AfterService" id="afterService"/>
    15. <bean class="advice.AdviceTest" id="adviceTest"/>
    16. <aop:config>
    17. <aop:pointcut id="point" expression="execution(* advice.AdviceTarget.*(..))"/>
    18. <aop:advisor advice-ref="afterService" pointcut-ref="point"/>
    19. aop:config>
    20. beans>

    运行结果:

    8、自定义增强

    创建自定义类 AdviceTest.java

    1. package advice;
    2. /**
    3. * @Author 不要有情绪的 ljy
    4. * @Date 2022/9/8 9:50
    5. * @Description:
    6. */
    7. public class AdviceTest {
    8. public void test() {
    9. System.out.println("我是一个普通类!");
    10. }
    11. }
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:aop="http://www.springframework.org/schema/aop"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans
    6. http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/aop
    8. http://www.springframework.org/schema/aop/spring-aop.xsd">
    9. <bean class="advice.AdviceTarget" id="adviceTarget"/>
    10. <bean class="advice.BeforeService" id="beforeService"/>
    11. <bean class="advice.AfterReturnService" id="afterReturnService"/>
    12. <bean class="advice.ExceptionService" id="exceptionService"/>
    13. <bean class="advice.AroundService" id="aroundService"/>
    14. <bean class="advice.AfterService" id="afterService"/>
    15. <bean class="advice.AdviceTest" id="adviceTest"/>
    16. <aop:config>
    17. <aop:pointcut id="point" expression="execution(* advice.AdviceTarget.*(..))"/>
    18. <aop:aspect ref="adviceTest">
    19. <aop:before method="test" pointcut-ref="point"/>
    20. aop:aspect>
    21. aop:config>
    22. beans>

            对以上xml文件进行解释,定义了 AdviceTest 类里面的test()方法为切入方法

            使用的测试方法不能是使用带异常的测试方法:

    1. package springTest;
    2. import advice.AdviceTarget;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. /**
    5. * @Author 不要有情绪的 ljy
    6. * @Date 2022/9/7 18:11
    7. * @Description:
    8. */
    9. public class AdviceTest {
    10. public static void main(String[] args) {
    11. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
    12. AdviceTarget target = context.getBean(AdviceTarget.class);
    13. target.testAdvice("p1", 123);
    14. // try {
    15. // target.testException();
    16. // } catch (Exception e) {
    17. // e.printStackTrace();
    18. // }
    19. }
    20. }

    运行结果:

    9、总结

    以上就是springAOP的切入增强的方式,

    为什么要存在切入增强?

            切入增强是为了拦截某个切入点,然后在该切入点进行扩展现有行为。

    要使用在什么样的场景?

            1、用于日志打印
            2、用于全局异常处理拦截
            3、返回值统一处理
            4、多数据源切换

            其目的是对业务逻辑的各个部分进行分拆,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

    万物明朗,可可爱爱!
    愿你天天有个好心情,热爱每一段代码!
    ଘ(੭ˊᵕˋ)੭ (开心) ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)
                               
                                                                                                                              ------不写代码不会凸的小刘

  • 相关阅读:
    zabbix6自动化配置监控项监控GPU
    如何用Postman做接口自动化测试
    【Flink实战】Flink自定义的Source 数据源案例-并行度调整结合WebUI
    Pyhon-每日一练(1)
    4-8网络层-网络层设备
    【ZLM】花屏现象记录
    javascript的call、apply、bind的实现
    [博客园首发] 写连载博客,历时1410天出版书籍《物联网软件架构设计与实现》
    c语言编程实例
    漏洞发展趋势
  • 原文地址:https://blog.csdn.net/qq_40834643/article/details/126759264