📅  最后修改于: 2023-12-03 15:20:12.443000             🧑  作者: Mango
AOP(Aspect Oriented Programming)是一种编程思想,是面向对象编程(OOP)的补充和扩展。AOP的核心思想是将系统分为核心业务和辅助业务,剥离出来的辅助业务独立成为横切关注点(Cross-cutting Concerns),实现系统功能的复用和解耦合,提高代码的可维护和可扩展性。
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依赖 -->
<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为系统添加日志打印、性能监控等功能,提高代码的可维护性和可扩展性。