Spring整合SpringAOP(基于aspectj)

Spring引入Spring AOP:面向切面编程(基于aspectj)

应用场景:环绕增强可以用来解决事务问题,前置/后置/返回值/异常增强可以用来添加日志处理

1、导包

 <!-- Spring AOP -->
 <dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjrt</artifactId>
     <version>1.9.9.1</version>
 </dependency>
 <dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjtools</artifactId>
     <version>1.9.9.1</version>
 </dependency>
 <dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjweaver</artifactId>
     <version>1.9.9.1</version>
 </dependency>
 <dependency>
     <groupId>aopalliance</groupId>
     <artifactId>aopalliance</artifactId>
     <version>1.0</version>
 </dependency>
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-aspects</artifactId>
     <version>5.3.18</version>
 </dependency>

2、在Spring配置文件中配置信息

 <!--使AspectJ注解起作用:为匹配的类自动生成代理对象-->
 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3、待增强类

接口

 public interface Calculator {
     int add(int a, int b);
     int sub(int a, int b);
     int div(int a, int b);
     int mut(int a, int b);
 }

实现类

 import org.springframework.stereotype.Component;
 ​
 @Component("calculator")
 public class CalculatorImpl implements Calculator {
 ​
     @Override
     public int add(int a, int b) {
         System.out.println("add方法被调用");
         return a + b;
     }
 ​
     @Override
     public int sub(int a, int b) {
         System.out.println("sub方法被调用");
         return a - b;
     }
 ​
     @Override
     public int div(int a, int b) {
         System.out.println("div方法被调用");
         return a / b;
     }
 ​
     @Override
     public int mut(int a, int b) {
         System.out.println("mut方法被调用");
         return a * b;
     }
 }

4、增强类

 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.After;
 import org.aspectj.lang.annotation.AfterReturning;
 import org.aspectj.lang.annotation.AfterThrowing;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.springframework.stereotype.Component;
 ​
 import java.util.Arrays;
 ​
 @Component  //为切面加入Spring自动扫描支持
 @Aspect  //加入AspectJ支持,声明类为切面
 public class LogAspect {
 ​
     /**
      * 前置增强
      */
     @Before("execution(public int com.xxx.demo.Calculator.*(int,int))")
     public void beforeMethod() {
         System.out.println("前置增强");
     }
 ​
     /**
      * 后置增强
      *
      * @param joinPoint 可以通过joinPoint获取所执行的方法以及该方法传入的参数
      */
     @After("execution(public int com.xxx.demo.Calculator.*(int,int))")
     public void afterMethod(JoinPoint joinPoint) {
         // 获取方法名称
         String methodName = joinPoint.getSignature().getName();
         System.out.println("方法名称:" + methodName);
         // 获取该方法传入的参数
         Object[] args = joinPoint.getArgs();
         System.out.println("方法参数:" + Arrays.toString(args));
         System.out.println("后置增强");
     }
 ​
     /**
      * 返回增强
      *
      * @param joinPoint 可以通过joinPoint获取所执行的方法以及该方法传入的参数
      * @param result    获取该方法的返回值
      */
     @AfterReturning(value = "execution(public int com.xxx.demo.Calculator.*(int,int))", returning = "result")
     public void afterReturningMethod(JoinPoint joinPoint, int result) {
         // 获取方法名称
         String methodName = joinPoint.getSignature().getName();
         System.out.println("方法名称:" + methodName);
         // 获取该方法传入的参数
         Object[] args = joinPoint.getArgs();
         System.out.println("方法参数:" + Arrays.toString(args));
         // 获取该方法执行的返回值
         System.out.println("方法返回值:" + result);
         System.out.println("返回增强");
     }
 ​
     /**
      * 异常增强
      *
      * @param joinPoint 可以通过joinPoint获取所执行的方法以及该方法传入的参数
      * @param ex        该方法所产生的异常
      */
     @AfterThrowing(value = "execution(public int com.xxx.demo.Calculator.*(int,int))", throwing = "ex")
     public void afterThrowingMethod(JoinPoint joinPoint, ArithmeticException ex) {
         // 获取方法抿成
         String methodName = joinPoint.getSignature().getName();
         System.out.println("方法名称:" + methodName);
         // 获取该方法所传入的返回值
         Object[] args = joinPoint.getArgs();
         System.out.println("方法参数:" + Arrays.toString(args));
         // 获取该方法产生的异常
         System.out.print("方法产生的异常:" + ex);
         System.out.println("异常增强");
     }
 ​
     /**
      * 环绕增强
      *
      * @param pjp 可以通过pjp获取方法名称、获取传入的参数以及可以通过proceed调用目标方法
      * @return java.lang.Object 返回目标方法执行后的结果
      */
     @Around(value = "execution(public int com.xxx.demo.Calculator.*(int,int))")
     public Object AroundMethod(ProceedingJoinPoint pjp) {
         Object res = null;
         String methodName = pjp.getSignature().getName();
         Object[] args = pjp.getArgs();
         try {
             System.out.println("环绕增强-->前置");
             //调用目标方法
             res = pjp.proceed();
             System.out.println("返回值:" + res);
             System.out.println("环绕增强-->返回");
         } catch (Throwable throwable) {
             System.out.println("环绕增强-->异常");
             throw new RuntimeException(throwable);
         }
         System.out.println("环绕增强-->后置");
         return res;
     }
 }

5、测试

 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.stereotype.Component;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 ​
 import javax.annotation.Resource;
 ​
 @ExtendWith(SpringExtension.class)
 @ContextConfiguration({"/spring.xml", "/mybatis.xml"})
 @Component
 public class DemoTest {
 ​
     @Resource
     private Calculator calculator;
 ​
     @Test
     void fun() {
         System.out.println(calculator.add(3, 2));
         System.out.println(calculator.sub(3, 2));
         System.out.println(calculator.div(3, 0));
         System.out.println(calculator.mut(3,2));
     }
 ​
 }

以下测试是对LogAspect.java中的增强方式依次单个或多个进行测试,单个时是将其他的增强方法注释掉

测试前置增强:

测试后置增强

测试返回增强

测试异常增强

测试正常环绕增强

测试异常环绕增强

异常时,环绕增强执行了环绕增强的前置增强和环绕增强的异常增强

所有增强均开始,测试执行顺序

无异常时,先执行环绕前置增强-->前置增强-->环绕增强调用方法-->返回增强-->后置增强-->环绕返回增强-->环绕后置增强

异常时,环绕前置增强-->前置增强-->环绕增强调用方法-->异常增强-->后置增强-->环绕异常增强

方式二:通过xml配置文件实现增强(不建议使用)

1、导入依赖,同上

2、在Spring配置文件中配置相关信息,同上

3、待增强类,同上

4、增强类

 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.ProceedingJoinPoint;
 ​
 import java.util.Arrays;
 ​
 public class LogAspect2 {
 ​
     /**
      * 前置增强
      */
     public void beforeMethod() {
         System.out.println("前置增强");
     }
 ​
     /**
      * 后置增强
      *
      * @param joinPoint 可以通过joinPoint获取所执行的方法以及该方法传入的参数
      */
     public void afterMethod(JoinPoint joinPoint) {
         // 获取方法名称
         String methodName = joinPoint.getSignature().getName();
         System.out.println("方法名称:" + methodName);
         // 获取该方法传入的参数
         Object[] args = joinPoint.getArgs();
         System.out.println("方法参数:" + Arrays.toString(args));
         System.out.println("后置增强");
     }
 ​
     /**
      * 返回增强
      *
      * @param joinPoint 可以通过joinPoint获取所执行的方法以及该方法传入的参数
      * @param result    获取该方法的返回值
      */
     public void afterReturningMethod(JoinPoint joinPoint, int result) {
         // 获取方法名称
         String methodName = joinPoint.getSignature().getName();
         System.out.println("方法名称:" + methodName);
         // 获取该方法传入的参数
         Object[] args = joinPoint.getArgs();
         System.out.println("方法参数:" + Arrays.toString(args));
         // 获取该方法执行的返回值
         System.out.println("方法返回值:" + result);
         System.out.println("返回增强");
     }
 ​
     /**
      * 异常增强
      *
      * @param joinPoint 可以通过joinPoint获取所执行的方法以及该方法传入的参数
      * @param ex        该方法所产生的异常
      */
     public void afterThrowingMethod(JoinPoint joinPoint, ArithmeticException ex) {
         // 获取方法抿成
         String methodName = joinPoint.getSignature().getName();
         System.out.println("方法名称:" + methodName);
         // 获取该方法所传入的返回值
         Object[] args = joinPoint.getArgs();
         System.out.println("方法参数:" + Arrays.toString(args));
         // 获取该方法产生的异常
         System.out.print("方法产生的异常:" + ex);
         System.out.println("异常增强");
     }
 ​
     /**
      * 环绕增强
      *
      * @param pjp 可以通过pjp获取方法名称、获取传入的参数以及可以通过proceed调用目标方法
      * @return java.lang.Object 返回目标方法执行后的结果
      */
     public Object AroundMethod(ProceedingJoinPoint pjp) {
         Object res = null;
         String methodName = pjp.getSignature().getName();
         Object[] args = pjp.getArgs();
         try {
             System.out.println("环绕增强-->前置");
             //调用目标方法
             res = pjp.proceed();
             System.out.println("返回值:" + res);
             System.out.println("环绕增强-->返回");
         } catch (Throwable throwable) {
             System.out.println("环绕增强-->异常");
             throw new RuntimeException(throwable);
         }
         System.out.println("环绕增强-->后置");
         return res;
     }
 }

5、增强xml配置

 
<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
 ​
     <bean class="com.xxx.demo.CalculatorImpl" id="calculator"></bean>
     <bean class="com.xxx.demo.LogAspect2" id="logAspect"></bean>
 ​
     <aop:config>
         <aop:pointcut id="pointcut"
                       expression="execution(public int com.xxx.demo.Calculator.*(int,int))"/>
         <aop:aspect ref="logAspect" order="1">
             <aop:before method="beforeMethod" pointcut-ref="pointcut"/>
             <aop:after method="afterMethod" pointcut-ref="pointcut"/>
             <aop:after-returning method="afterReturningMethod" pointcut-ref="pointcut"
                                  returning="result"/>
             <aop:after-throwing method="afterThrowingMethod" pointcut-ref="pointcut"
                                 throwing="ex"/>
             <aop:around method="AroundMethod" pointcut-ref="pointcut"/>
         </aop:aspect>
     </aop:config>
 </beans>

6、测试

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.annotation.Resource;

@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/spring.xml", "/mybatis.xml", "/aspectj.xml"})
@Component
public class DemoTest2 {

    @Resource
    private Calculator calculator;

    @Test
    void fun() {
        //System.out.println(calculator.add(3, 2));
        //System.out.println(calculator.sub(3, 2));
        System.out.println(calculator.div(3, 0));
        //System.out.println(calculator.mut(3,2));
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值