Spring AOP學習筆記(一)-AOP相關概念和基於註解方式實現AOP的規則
阿新 • • 發佈:2019-02-05
一、 Spring AOP 概念
其實AOP就是要將我們Aspect中的Pointcut和Target Object中的JointPoint動態的連線起來,同時我們通過Advice指明Pointcut執行的一個時機。這是個人理解
AOP相關名詞解釋
名詞 | 解釋 |
---|---|
Ascpect | 橫跨多個類的模組化關注點 |
Pointcut | 指明Aspect和哪個連線點進行連線 |
Advice | Advice是單一橫切關注點的邏輯的載體,他代表將會織入到JointPoint的橫切邏輯;也可以說是Aspect的具體的方法 |
Target Object | Aspect關注的物件 |
Joint Point | 表示目標物件執行的方法 |
Advice 的分類
Adice種類 | 解釋 |
---|---|
Before Advice | 在Joint Point(執行方法)之前執行Pointcut方法) |
After return Advice | 在 Joint Point(執行方法)正常退出時執行Pointcut |
After throwing Advice | 在Joint Point(執行方法)丟擲異常退出時執行Pointcut |
After Advice | 在Joint Point(執行方法)退出(不管是正常退出還是拋異常退出)時執行Pointcut |
Around Advice | 在Joint Point(執行方法)被呼叫之前和之後都會執行Pointcut |
二、註解的方式宣告一個切面
2.1、切面中涉及的註解
註解 | 宣告地點 | 使用方式 |
---|---|---|
@Aspect | 宣告在類上 | 表明這時一個Aspect |
@Pointcut | 宣告在Pointcut(Aspect的方法)上 | 指明和哪個Target Object 的Joint Point進行連線 |
@Before | 宣告註解在Aspect的方法上 | 表明在Joint Point(執行方法)之前執行Aspect的方法 |
@AfterReturning | 宣告註解在Aspect的方法上 | 表明在 Joint Point(執行方法)正常退出時執行Aspect的方法 |
@AfterThrowing | 宣告註解在Aspect的方法上 | 表明在Joint Point(執行方法)丟擲異常退出時執行執行Aspect的方法 |
@After | 宣告註解在Aspect的方法上 | 表明在Joint Point(執行方法)被呼叫之前和之後都會執行執行Aspect的方法 |
2.2、宣告一個Aspect
package com.zbt.day03;
import org.aspectj.lang.annotation.*;
@Aspect
public class AfterThrowingAspect {
}
在Spring上下文中配置Bean注入,因為Aspect也是一個類,需要使用注入的方式讓Spring管理一個Bean
<aop:aspectj-autoproxy/>//開啟Spring AOP自動代理功能
<bean id="audience" class="com.zbt.day01.Audience"></bean>
因為使用@AspectJ表示我們已經放棄了自動代理(auto-proxy)的方式,因此我們需要使用註解的方式@Component或者在Spring上下文中配置自動代理。
2.3、切點表示式
方法 | 描述 |
---|---|
execution(public * *(..)) | 執行那些方法為public的Joint Point |
execution(* set*(..)) | 執行那些方法名為set的Joint Point |
execution(* com.xyz.service.AccountService.*(..)) | 執行com.xyz.service.AccountService中所有的JointPoint(方法) |
execution(* com.xyz.service.* . *(..) | 執行com.xyz.service包中任何的JointPoint(方法) |
execution(* com.xyz.service..* . *(..)) | 執行com.xyz.service..* . *(..))包和其子包下面所有的JointPoint(方法) |
within(com.xyz.service.*) | 執行所有在com.xyz.service包中所有的JointPoint(方法) |
this(com.xyz.service.AccountService) | |
target(com.xyz.service.AccoutnService) | 執行實現了com.xyz.service.AccoutnService介面的所有的類的JointPoint(方法) |
args(java.io.Serializable) | 執行任何連結點引數只有一個,且指定引數型別為執行時Serializable(我們可以指定任意引數型別,只要是我們需要的) |
@target(org.springframework.transaction.annotation.Transactional) | 執行目標物件註解了@Transaction註解的方法 |
bean(tradeService) | |
bean(*Service) |
2.4、宣告一個Advice
@Before
@Before("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void beforeJointPoint(){
System.out.println("在Joint Point執行前執行此方法");
}
@AfterThrowing
@AfterThrowing("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void printAbonormal(){
System.out.println("在Joint Point丟擲異常後執行此方法");
}
@AfterReturning
@AfterReturning("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void printNormal(){
System.out.println("在Joint Point正常退出執行此方法");
}
@After
@After("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void print(){
System.out.println("不管Joint Point是正常退出還是異常退出都執行此方法");
}
@Round
示例
編寫Aspect和Advice
package com.zbt.day03;
import org.aspectj.lang.annotation.*;
@Aspect
public class AfterThrowingAspect {
@Before("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void beforeJointPoint(){
System.out.println("在Joint Point執行前執行此方法");
}
@AfterThrowing("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void printAbonormal(){
System.out.println("在Joint Point丟擲異常後執行此方法");
}
@AfterReturning("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void printNormal(){
System.out.println("在Joint Point正常退出執行此方法");
}
@After("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
public void print(){
System.out.println("不管Joint Point是正常退出還是異常退出都執行此方法");
}
}
編寫Target Object和Joint Point(Target 中的方法)
package com.zbt.day03;
/**
* Created by luckyboy on 2018/8/15.
*/
public class ThrowExceptionApp {
public int division(int a,int b){
int i = 0;
try{
i = a/b;
}catch (Exception e){
throw e;
}
return i;
}
}
程式碼測試
package com.zbt.day03;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAdvice {
@Test
public void testPerformance(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationConfig.xml");
ThrowExceptionApp throwExceptionApp = context.getBean("throwExceptionApp",ThrowExceptionApp.class);
throwExceptionApp.division(1,1);
}
}