摘要: 記得今年年初剛開始面試的時候,被問的最多的就是你知道Spring的兩大核心嘛?那你說說什麼是AOP,什麼是IOC?我相信你可能也被問了很多次了。 1、到底是什麼是AOP? 所謂AOP也就是面向切面編程,能夠讓我們在不影響原有業務功能的前提下,橫切擴展新的功能。
記得今年年初剛開始面試的時候,被問的最多的就是你知道Spring的兩大核心嘛?那你說說什麼是AOP,什麼是IOC?我相信你可能也被問了很多次了。
私信“555”與獲取資料,大牛一起交流~~
1、到底是什麼是AOP?
所謂AOP也就是面向切面編程,能夠讓我們在不影響原有業務功能的前提下,橫切擴展新的功能。這裡面有一個比較顯眼的詞我們需要注意一下,橫切,它是基於橫切面對程序進行擴展的。
2、AOP相關術語
在Spring的AOP中有很多的術語,而且容易混淆,大家一定要先搞清楚這幾個概念:
● 連接點(Joinpoint):在程序執行過程中某個特定的點,比如類初始化前、類初始化後,方法調用前,方法調用後;
● 切點(Pointcut) :所謂切點就是你所切取的類中的方法,比如你橫切的這個類中有兩個方法,那麼這兩個方法都是連接點,對這兩個方法的定位就稱之為切點;
● 增強(Advice):增強是織入到連接點上的一段程序,另外它還擁有連接點的相關信息;
● 目標對象(Target):增強邏輯的織入目標類,就是我的增強邏輯植入到什麼位置;
● 引介(Introduction):一種特殊的增強,它可以為類添加一些屬性喝方法;
● 織入(Weaving):織入就是講增強邏輯添加到目標對象的過程;
● 代理(Proxy):一個類被AOP織入增強後,就會產生一個結果類,他是融合了原類和增強邏輯的代理類;
● 切面(Aspect):切面由切點和增強組成,他是橫切邏輯定義和連接點定義的組成;
3、AOP功能實踐
我們這裡主要是學習SpringBoot中的一些功能,所以我們這裡用的是SpringBoot工程,版本也是最新的2.0.5版本。
創建SpringBoot工程就不說了,我們直接引入Maven的依賴:
首先我們來創建一個Controller類:
@RestController
public class LoginController {
@GetMapping(value = "/username")
public String getLoginUserName(String userName, Integer age) {
return userName + " --- " + age;
}
}
創建切面:
@Aspect
@Component
public class LogAspect {
/**
* 功能描述: 攔截對這個包下所有方法的訪問
*
* @param:[]
* @return:void
**/
@Pointcut("execution(* com.example.springbootaop.controller.*.*(..))")
public void loginLog() {
}
// 前置通知
@Before("loginLog()")
public void loginBefore(JoinPoint joinPoint) {
// 我們從請求的上下文中獲取request,記錄請求的內容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
System.out.println("請求路徑 : " + request.getRequestURL());
System.out.println("請求方式 : " + request.getMethod());
System.out.println("方法名 : " + joinPoint.getSignature().getName());
System.out.println("類路徑 : " + joinPoint.getSignature().getDeclaringTypeName());
System.out.println("參數 : " + Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(returning = "object", pointcut = "loginLog()")
public void doAfterReturning(Object object) {
System.out.println("方法的返回值 : " + object);
}
// 方法發生異常時執行該方法
@AfterThrowing(throwing = "e",pointcut = "loginLog()")
public void throwsExecute(JoinPoint joinPoint, Exception e) {
System.err.println("方法執行異常 : " + e.getMessage());
}
// 後置通知
@After("loginLog()")
public void afterInform() {
System.out.println("後置通知結束");
}
// 環繞通知
@Around("loginLog()")
public Object surroundInform(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("環繞通知開始...");
try {
Object o = proceedingJoinPoint.proceed();
System.out.println("方法環繞proceed,結果是 :" + o);
return o;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
}
註解概述:
● @Apsect:將當前類標識為一個切面;
● @Pointcut:定義切點,這裡使用的是條件表達式;
● @Before:前置增強,就是在目標方法執行之前執行;
● @AfterReturning :後置增強,方法退出時執行;
● @AfterThrowing:有異常時該方法執行;
● @After:最終增強,無論什麼情況都會執行;
● @Afround:環繞增強;
測試:
異常測試:
4、定義自定義註解
應用場景:在我之前上個項目的時候,有這樣一個註解,就是在訪問其他接口的時候必須要登錄,那麼這個時候我們就定義一個註解,讓它去對用戶是否登錄進行校驗,那麼基於這樣的一個場景,我們來定義一個校驗登錄的註解。
創建一個註解:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
String desc() default "驗證是否登錄";
}
創建一個AOP切面:
@Aspect
@Component
public class LoginAspect {
@Pointcut(value = "@annotation(com.example.springbootaop.annotation.Auth)")
public void access() {
}
@Before("access()")
public void before() {
System.out.println("開始驗證用戶是否登錄...");
}
@Around("@annotation(auth)")
public Object around(ProceedingJoinPoint pj, Auth auth) {
// 獲取註解中的值
System.out.println("註解中的值 : " + auth.desc());
try {
// 檢驗是否登錄 true 已經登錄 false 未登錄
Boolean flag = false;
if (flag == true) {
return "登錄成功";
} else {
return "未登錄";
}
} catch (Throwable throwable) {
return null;
}
}
}
測試未登錄:
測試登錄:
私信“555”與獲取資料,大牛一起交流~~
這樣我們就可以簡單的實現了一個登錄校驗的註解。
通過今天的分享你會使用AOP和自定義註解了嗎?我把源碼的地址放在下面,有興趣的朋友可以看看。
閱讀更多 架構月亮姨 的文章