常用的編程范式
AOP 是什么
- 是一種編程方式,不是編程語言
- 解決特定問題,不能解決所有的問題
- OOP的補充,不是代替
AOP 初衷
- DRY: Don't repeat yourself(代碼重復)
- SoC:Separation of Concerns(關注點分離)
- 水平分離:展示層-> 服務層 -> 持久層
- 垂直分離:模塊划分(訂單、庫存等)
- 切面分離:分離功能性需求與非功能性需求
AOP的優點
- 集中處理某一關注點/橫切邏輯
- 可以很方便地添加/刪除關注點
- 侵入性少,增強代碼可讀性及可維護性
AOP的應用場景
- 權限控制
- 緩存控制
- 性能監控
- ...
支持AOP的語言
- Java、Python、PHP...
SpringAOP使用詳解
首先,我整理了一張圖,讓大家更好的梳理SpringAOP的使用
@Poincut 詳解
匹配包/類型_ within()
-
匹配ProductService類里頭的所有方法
-
@Pointcut("within(com.zhb.service.ProductService)")
-
匹配com.zhb包及子包下所有類的方法
-
@Pointcut("within(com.zhb..*)")
匹配對象
-
匹配AOP對象的目標對象為指定類型的方法,即LogService的aop代理對象的方法
-
@Pointcut("this(com.zhb.log.Loggable)")
-
匹配實現Loggable接口的目標對象(而不是aop代理后的對象)的方法
-
@Pointcut("target(com.zhb.log.Loggable)")
-
this 可以攔截 DeclareParents(Introduction)
-
target 不攔截 DeclareParents(Introduction)
-
匹配所有以Service結尾的bean里頭的方法
-
@Pointcut("bean(*Service)")
匹配參數 args()
-
匹配任何以find開頭而且只有一個Long參數的方法
-
@Pointcut("execution(* ..find(Long))")
-
匹配任何以find開頭的而且第一個參數為Long型的方法
-
@Pointcut("execution(* ..find(Long,..))")
-
匹配任何只有一個Long參數的方法
-
@Pointcut("within(com.zhb..*) && args(Long)")
-
匹配第一個參數為Long型的方法
-
@Pointcut("within(com.zhb..*) && args(Long,..)")
匹配注解
- 匹配方法標注有AdminOnly的注解的方法
- @Pointcut("@annotation(com.zhb.anno.AdminOnly) && within(com.zhb..*)")
- 匹配標注有NeedSecured的類底下的方法 //class級別
- @Pointcut("@within(com.zhb.anno.NeedSecured) && within(com.zhb..*)")
- 匹配標注有NeedSecured的類及其子類的方法 //runtime級別
- 在spring context的環境下,二者沒有區別
- @Pointcut("@target(com.zhb.anno.NeedSecured) && within(com.zhb..*)")
- 匹配傳入的參數類標注有Repository注解的方法
- @Pointcut("@args(com.zhb.anno.NeedSecured) && within(com.zhb..*)")
匹配方法
-
匹配任何公共方法
-
@Pointcut("execution(public * com.zhb.service..(..))")
-
匹配com.zhb包及子包下Service類中無參方法
-
@Pointcut("execution(* com.zhb..Service.())")
-
匹配com.zhb包及子包下Service類中的任何只有一個參數的方法
-
@Pointcut("execution(* com.zhb..Service.(*))")
-
匹配com.zhb包及子包下任何類的任何方法
-
@Pointcut("execution(* com.zhb...(..))")
-
匹配com.zhb包及子包下返回值為String的任何方法
-
@Pointcut("execution(String com.zhb...(..))")
-
匹配異常
-
execution(public * com.zhb.service..(..) throws java.lang.IllegalAccessException)
其實,這么多實際工作中用到的比較少,我平時就用過execution 這一個。
Advice 詳解
- @Before(value = "matchLongArg() && args(productId)")
- public void beforeWithArgs(Long productId)
- @AfterReturning(value = "matchReturn()",returning = "returnValue")
- public void getReulst(Object returnValue)
給出一段常用代碼
@Pointcut("within(com.zhb.controller.GirlController)")
public void mathType(){}
@Before(value = "mathType() && args(obj)")
public void before(Object obj){
System.out.println("這里是目標方法執行前先執行");
//獲取參數
System.out.println("這里是目標方法的參數"+obj.toString());
}
@AfterReturning(returning = "entity",value = "mathType()")
public void after(JoinPoint joinPoint,Object entity){
System.out.println("這里是目標方法執行完並成功返回結果 正常結束后才執行");
System.out.println("方法的返回結果為"+entity);
System.out.println("目標方法內的參數為"+ Arrays.asList(joinPoint.getArgs()));
}
@AfterThrowing(throwing = "e",value = "mathType()")
public void mathThrow(Throwable e){
System.out.println("這里是目標方法拋出異常后才執行");
System.out.println("異常信息為"+e);
}
大家再用到的時候可以自行搜索