1生均、簡介
-
AOP即面向切面編程Aspect Oriented Program。
- 面向切面編程將系統(tǒng)功能分為核心業(yè)務(wù)功能和切面功能腥刹,核心業(yè)務(wù)功能主要是注冊登錄马胧、數(shù)據(jù)庫操作等,切面功能主要有日志衔峰、權(quán)限佩脊、性能分析等。
- AOP將與核心功能一起調(diào)用的任務(wù)和邏輯分離開并封裝起來垫卤,有助于減少系統(tǒng)的重復(fù)代碼威彰,降低模塊間的耦合度。
2穴肘、AOP中的概念
- 切點(PointCut):指定切入的類或方法(
)
- 通知(Advice):對方法在什么時間(
)需要執(zhí)行的操作(
)
- 切面(Aspect):切點+通知
- 織入(Weaving):將切面加入到對象中歇盼,并創(chuàng)建代理的過程。
3评抚、AOP的通知類型
- before(前置通知):在方法開始執(zhí)行前執(zhí)行
- after(后置通知): 在方法執(zhí)行后執(zhí)行
- afterReturning(返回后通知): 在方法返回后執(zhí)行
- afterThrowing(異常通知): 在拋出異常時執(zhí)行
- around(環(huán)繞通知): 在方法執(zhí)行前和執(zhí)行后都會執(zhí)行
4豹缀、快速入門
- 構(gòu)建spring boot項目
- 引入AOP依賴
<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("執(zhí)行運算:" + signature.getName()); // 獲取方法名稱
System.out.println("執(zhí)行參數(shù):" + Arrays.toString(joinPoint.getArgs())); // 方法參數(shù)
}
@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("執(zhí)行結(jié)果:" + 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...
執(zhí)行運算:divide
執(zhí)行參數(shù):[13, 2]
除法:13/2
After...
Returning...
執(zhí)行結(jié)果:6
- 環(huán)繞通知(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(); // 執(zhí)行目標方法
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...