轉載請聲明出處!安全
Spring AOP爲咱們提供了一種更簡潔的代碼編寫方法。主要用來隔離業務邏輯代碼,下降非業務代碼的侵入性。好比像日誌記錄,安全管理,事務管理等,若是直接寫到業務代碼裏,侵入性大,代碼閱讀性差。bash
若是你的項目使用了AOP,那麼能夠給你的類裏的方法添加更多功能,讓代碼更簡潔易讀。app
在這裏,James不打算和你們討論AOP的基礎知識。若是沒有用過AOP的同窗,能夠先百度簡單看一下AOP的基本概念,咱們將主要關注Spring AOP應用程序。性能
在咱們開發的任何應用程序中,如下的這些代碼我相信必定是你們都寫過的:ui
//服務層
@Service
public class OrderServiceImpl {
public Order queryOrder() {
System.out.println("Reading from collectionA");
return new Order("1","2019-07-11");
}
public int updateOrder() {
System.out.println("Writing to collectionA");
return 1;
}
}
//控制層
@Controller
public class OrderController {
@Autowired
OrderServiceImpl orderServiceImpl;
//訂單查詢
@RequestMapping("query")
public Order queryOrder() {
return orderServiceImpl.queryOrder();
}
//訂單修改
@RequestMapping("update")
public int updateOrder() {
return orderServiceImpl.updateOrder();
}
}
複製代碼
在上面的示例中,咱們在控制層中有一個OrderController類和一個OrderServiceImpl業務類。spa
若是如今有這麼一個需求:日誌
在咱們的應用程序的第一個版本中,它是沒有受權功能,如今的需求是要加一個受權功能。code
在上面的示例中,在咱們操做訂單信息以前(不論是查詢仍是修改)添加一個檢查用戶是否爲admin的功能。orm
實現此功能的一種方法是建立Authorization類和isAuthorized方法來檢查用戶是否被受權。那麼咱們須要更新OrderServiceImpl的全部方法,並經過調用isAuthorized方法來檢查受權。對象
@Component
public class OrderServiceImpl {
public Order queryOrder() {
//判斷當前登錄用戶是否有權限查詢
if (Authorization.isAuthorised(Session.getUserId())){
System.out.println("Reading from collectionA");
return new Order("1","2019-07-11");
}
}
public int updateOrder() {
//判斷當前登錄用戶是否有權限修改
if (Authorization.isAuthorised(Session.getUserId())){
System.out.println("Writing to collectionA");
return 1;
}
}
}
複製代碼
可是,這種方法存在缺點。咱們須要修改OrderServiceImpl類的每一個方法,而且在全部方法中重複調用isAuthorized方法的相同代碼以檢查受權。
若是不更改現有類,能不能完成受權檢查功能呢?
固然能夠,AOP就能夠實現。
如今定義一個AuthorizationCheck類,能夠爲OrderServiceImpl類建立一個切入點。在建議中,咱們檢查用戶是不是管理員,而後咱們繼續;不然,咱們不操做。
無需在OrderServiceImpl類中進行任何更改。
代碼以下:
@Aspect
@Configuration
public class AuthorizationCheck {
//使用Around切面攔截OrderServiceImpl類的全部方法,在調用OrderServiceImpl方法時自動檢查權限
@Around("execution(**com.enjoy.aop.OrderServiceImpl.*(..))")
public void check (ProceedingJoinPoint jp) {
try {
if(Authorization.isAuthorised(Session.getUserId())) {
jp.proceed();//手動執行目標方法,至關於調用OrderServiceImpl的某個方法
}
else {
System.out.println("User not Authorised");
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
複製代碼
如今,對於對OrderServiceImpl類的任何方法的任何調用,只有在知足時纔會調用訂單相關方法。
以上可見,在不更改現有類的狀況下,咱們完成了受權功能。固然除了這種使用方式外,咱們還能夠監控性能,好比監控OrderServiceImpl類裏方法執行的時間狀況,如何操做呢?見下
建立一個名爲TurnAroundTime自定義註解,用來檢查目標方法執行的性能與時間。
如下是一個例子:首先,咱們須要自定義一個註解。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public@interface TurnAroundTime {
}
複製代碼
咱們想檢查的對象爲方法,因此這裏的目標類型是Method,@Target(ElementType.METHOD)。
RetentionPolicy是運行時,由於咱們想在運行時應用它們。接下來,咱們定義切面。
@Aspect
@Configuration
public class PerformanceCheck {
//攔截com.enjoy.aop包下的全部方法,當方法聲明TurnAroundTime註解時,
//都須要執行watchPerformance切面方法
@Around("execution(** com.enjoy.aop.*.*.*(..))&& @annotation(TurnAroundTime)")
public void watchPerformance(ProceedingJoinPoint jp) {
Instant start = Instant.now();//調方法前計時
try {
jp.proceed();//手動執行目標方法,至關於調用OrderServiceImpl的某個方法
} catch (Throwable e) {
e.printStackTrace();
}
Instant finish = Instant.now();//調方法結束後計時
long timeElapsed = Duration.between(start,finish).toMillis();//調用方法耗時多少
System.out.println("Total Turnaround time:" + timeElapsed);
}
}
複製代碼
咱們使用切入點定義一個切面,用該切面來監聽目標方法執行狀況。記錄目標方法執行前和執行以後的時間差。
所以,若咱們想要測量目標方法的性能時,咱們須要使用自定義註釋@TurnAroundTime來註釋該方法。
代碼以下:
@Component
public class OrderServiceImpl {
@TurnAroundTime
public Order queryOrder() {
//判斷當前登錄用戶是否有權限查詢
if (Authorization.isAuthorised(Session.getUserId())){
System.out.println("Reading from collectionA");
return new Order("1","2019-07-11");
}
}
@TurnAroundTime
public int updateOrder() {
//判斷當前登錄用戶是否有權限修改
if (Authorization.isAuthorised(Session.getUserId())){
System.out.println("Writing to collectionA");
return 1;
}
}
}
複製代碼
你們能夠看到,SpringAOP玩熟悉後,能夠解決不少代碼冗餘問題,方便咱們開發,自定義註解能讓咱們更好的美化代碼,減小代碼的侵入性,本節就寫到這裏吧。
你的贊和關注是我繼續創做的動力~