📜  Spring AOP示例(1)

📅  最后修改于: 2023-12-03 15:20:12.443000             🧑  作者: Mango

Spring AOP示例

什么是AOP?

AOP(Aspect Oriented Programming)是一种编程思想,是面向对象编程(OOP)的补充和扩展。AOP的核心思想是将系统分为核心业务和辅助业务,剥离出来的辅助业务独立成为横切关注点(Cross-cutting Concerns),实现系统功能的复用和解耦合,提高代码的可维护和可扩展性。

Spring AOP的实现

Spring AOP是基于代理模式实现的。代理模式是指一个对象(代理对象)代表另一个对象(目标对象)进行一些操作。Spring AOP的核心是AOP代理(Aspect Oriented Proxy),Spring实现了两种代理机制:基于JDK的动态代理和基于CGLib的动态代理。其中,基于JDK的动态代理适用于面向接口的代理,而基于CGLib的动态代理适用于非接口的代理。

Spring AOP的实现依赖于AspectJ框架,但它并不需要我们手动使用AspectJ框架。Spring AOP支持最常见的切面类型,包括前置通知(Before advice)、后置通知(After advice)、异常通知(After-throwing advice)、最终通知(After-returning advice)和环绕通知(Around advice)。

Spring AOP示例

下面,我们通过一个简单的示例来学习Spring AOP的使用。

环境搭建

首先,我们需要搭建Spring AOP的环境。我们需要使用以下依赖(已经省略了版本号):

<!-- Spring AOP依赖 -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
</dependency>

<!-- Spring Aspects依赖 -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
</dependency>
编写代码

我们定义一个接口Calculator和一个实现类CalculatorImpl,用于实现加减乘除四种运算操作。然后,我们使用Spring AOP为该实现类添加日志打印的功能。

public interface Calculator {
    int add(int i, int j);

    int sub(int i, int j);

    int mul(int i, int j);

    int div(int i, int j);
}

@Component
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int i, int j) {
        int result = i + j;
        System.out.printf("%d + %d = %d%n", i, j, result);
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        System.out.printf("%d - %d = %d%n", i, j, result);
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        System.out.printf("%d * %d = %d%n", i, j, result);
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        System.out.printf("%d / %d = %d%n", i, j, result);
        return result;
    }
}

@Aspect
@Component
public class CalculatorLoggingAspect {
    @Before("execution(public int Calculator.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.printf("调用方法:%s,参数:%s%n", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(pointcut = "execution(public int Calculator.*(..))", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.printf("方法:%s,返回值:%d%n", joinPoint.getSignature().getName(), result);
    }

    @AfterThrowing(pointcut = "execution(public int Calculator.*(..))", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.printf("方法:%s,异常:%s%n", joinPoint.getSignature().getName(), e);
    }
}
测试代码

我们使用JUnit和Spring进行单元测试,测试代码如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class CalculatorTest {
    @Autowired
    private Calculator calculator;

    @Test
    public void testAdd() {
        int result = calculator.add(1, 2);
        assertEquals(3, result);
    }

    @Test
    public void testSub() {
        int result = calculator.sub(2, 1);
        assertEquals(1, result);
    }

    @Test
    public void testMul() {
        int result = calculator.mul(2, 3);
        assertEquals(6, result);
    }

    @Test
    public void testDiv() {
        int result = calculator.div(6, 3);
        assertEquals(2, result);
    }
}
总结

Spring AOP是一个强大的AOP框架,它支持基于JDK和CGLib的动态代理机制,支持最常见的切面类型。在实际开发中,我们可以使用Spring AOP为系统添加日志打印、性能监控等功能,提高代码的可维护性和可扩展性。