1、简介
-
AOP即面向切面编程Aspect Oriented Program。
- 面向切面编程将系统功能分为核心业务功能和切面功能,核心业务功能主要是注册登录、数据库操作等,切面功能主要有日志、权限、性能分析等。
- AOP将与核心功能一起调用的任务和逻辑分离开并封装起来,有助于减少系统的重复代码,降低模块间的耦合度。
2、AOP中的概念
- 切点(PointCut):指定切入的类或方法()
- 通知(Advice):对方法在什么时间()需要执行的操作()
- 切面(Aspect):切点+通知
- 织入(Weaving):将切面加入到对象中,并创建代理的过程。
3、AOP的通知类型
- before(前置通知):在方法开始执行前执行
- after(后置通知): 在方法执行后执行
- afterReturning(返回后通知): 在方法返回后执行
- afterThrowing(异常通知): 在抛出异常时执行
- around(环绕通知): 在方法执行前和执行后都会执行
4、快速入门
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
public class Calculator {
public int divide(int a, int b) {
System.out.println("除法:" + a + "/" + b);
return a / b;
}
public int add(int a, int b) {
System.out.println("加法:" + a + "+" + b);
return a + b;
}
}
@Aspect
public class CalculatorAop {
//切点 Calculator的+-*/方法
@Pointcut("execution(public int com.samllbear.aopdemo.service.Calculator.divide(..))")
public void pointCut() {}
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println("Before...");
Signature signature = joinPoint.getSignature(); // 获取方法的签名
System.out.println("执行运算:" + signature.getName()); // 获取方法名称
System.out.println("执行参数:" + Arrays.toString(joinPoint.getArgs())); // 方法参数
}
@After("pointCut()")
public void after() {
System.out.println("After...");
}
@AfterReturning(value = "pointCut()", returning = "result")
public void afterReturning(Object result) {
System.out.println("Returning...");
System.out.println("执行结果:" + result);
}
@AfterThrowing(value = "pointCut()", throwing = "exception")
public void afterThrowing(Exception exception) {
System.out.println("Throwing...");
System.out.println(exception.getMessage());
}
}
@Configuration
@EnableAspectJAutoProxy // 开启aop
public class CalculatorConfig {
@Bean // 注入计算器
public Calculator calculator() {
return new Calculator();
}
@Bean // 注入aop
public CalculatorAop calculatorAop() {
return new CalculatorAop();
}
}
class AopDemoApplicationTests {
@Test
public void divideTest() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(CalculatorConfig.class);
// 注意只有注入容器的bean AOP才会生效
Calculator calculator = context.getBean(Calculator.class);
// calculator.divide(13, 0); // throwing... /By Zero
calculator.divide(13, 2);
}
}
Before...
执行运算:divide
执行参数:[13, 2]
除法:13/2
After...
Returning...
执行结果:6
- 环绕通知(Around)可以用来替换以上四种通知
在CalculatorAop.class
添加以下代码
private static final Logger log = LoggerFactory.getLogger(CalculatorAop.class);
@Pointcut("execution(public int com.samllbear.aopdemo.service.Calculator.add(..))")
public void addPointCut() {}
@Around("addPointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
try {
System.out.println("around begin...");
Object o = joinPoint.proceed(); // 执行目标方法
System.out.println("around end...");
return o;
} catch (Throwable e) {
System.out.println("around throwing...");
log.error(e.getMessage());
throw e;
} finally {
System.out.println("around returning...");
}
}
@Test
public void addTest() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(CalculatorConfig.class);
Calculator calculator = context.getBean(Calculator.class);
calculator.add(13, 0);
}
around begin...
加法:13+0
around end...
around returning...
网友评论