1. 概述
本文將討論在 Spring 中可以創建的不同類型的 AOP 建議。
建議 (Advice) 是在特定切入點由方面執行的動作。 不同類型的建議包括“around”、“before”和“after”建議。 方面的主要目的是支持橫切關注點,例如日誌記錄、性能分析、緩存和事務管理。
如果您想更深入地瞭解切入點表達式,請查看之前的介紹。
2. 啓用建議 (Enabling Advice)
在使用 Spring 時,您可以使用 AspectJ 註解聲明建議,但您必須首先在您的配置類上應用 @EnableAspectJAutoProxy 註解,這將會啓用對使用 AspectJ 的 @Aspect 註解標記的組件的處理支持。@Configuration
@EnableAspectJAutoProxy
public class AopConfiguration {
...
}2.1. Spring Boot
在 Spring Boot 項目中,我們無需顯式地使用 <em >@EnableAspectJAutoProxy</em></em >。 專門的AopAutoConfiguration會啓用 Spring 的 AOP 支持,如果Aspect 或 `Advice 存在於 classpath 中。
3. 建議前置
此建議,正如其名稱所示,將在連接點之前執行。 它除非拋出異常,否則不會阻止方法繼續執行。
請考慮以下僅用於記錄方法名稱的方面:
@Component
@Aspect
public class LoggingAspect {
private Logger logger = Logger.getLogger(LoggingAspect.class.getName());
@Pointcut("@target(org.springframework.stereotype.Repository)")
public void repositoryMethods() {};
@Before("repositoryMethods()")
public void logMethodCall(JoinPoint jp) {
String methodName = jp.getSignature().getName();
logger.info("Before " + methodName);
}
}logMethodCall 建議將會在由repositoryMethods 切入點定義的任何存儲庫方法執行之前執行。
4. 後置建議
使用@After註解聲明的後置建議,在匹配的方法執行完畢後執行,無論是否拋出異常。
在某種程度上,它與finally塊類似。如果您需要建議僅在正常執行後觸發,則應使用由@AfterReturning註解聲明的返回式建議。如果您希望您的建議僅在目標方法拋出異常時觸發,則應使用throwing advice,該建議由@AfterThrowing註解聲明。
假設我們希望在創建新的Foo實例時通知某些應用程序組件。我們可以從FooDao發佈事件,但這將違反單一職責原則。
相反,我們可以通過定義以下方面來實現此目的:
@Component
@Aspect
public class PublishingAspect {
private ApplicationEventPublisher eventPublisher;
@Autowired
public void setEventPublisher(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Pointcut("@target(org.springframework.stereotype.Repository)")
public void repositoryMethods() {}
@Pointcut("execution(* *..create*(Long,..))")
public void firstLongParamMethods() {}
@Pointcut("repositoryMethods() && firstLongParamMethods()")
public void entityCreationMethods() {}
@AfterReturning(value = "entityCreationMethods()", returning = "entity")
public void logMethodCall(JoinPoint jp, Object entity) throws Throwable {
eventPublisher.publishEvent(new FooCreationEvent(entity));
}
}首先請注意,通過使用 @AfterReturning> 註解,我們可以訪問目標方法的返回值。其次,通過聲明一個類型為 JoinPoint 的參數,我們可以訪問目標方法調用的參數。
接下來,我們創建一個監聽器,它將簡單地記錄事件:
@Component
public class FooCreationEventListener implements ApplicationListener<FooCreationEvent> {
private Logger logger = Logger.getLogger(getClass().getName());
@Override
public void onApplicationEvent(FooCreationEvent event) {
logger.info("Created foo instance: " + event.getSource().toString());
}
}5. 關於建議(Around Advice)
關於建議(Around Advice)包圍着一個切入點,例如方法調用。
這是最強大的建議類型。 關於建議(Around Advice)可以執行在方法調用前後自定義的行為。 它還負責決定是否繼續執行切入點或通過提供自己的返回值或拋出異常來簡短地中斷建議的方法執行。
為了演示其用法,假設我們想測量方法執行時間。 讓我們為這個目的創建一個Aspect:
@Aspect
@Component
public class PerformanceAspect {
private Logger logger = Logger.getLogger(getClass().getName());
@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositoryClassMethods() {};
@Around("repositoryClassMethods()")
public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
long start = System.nanoTime();
Object retval = pjp.proceed();
long end = System.nanoTime();
String methodName = pjp.getSignature().getName();
logger.info("Execution of " + methodName + " took " +
TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
return retval;
}
}此建議會在 repositoryClassMethods 切入點匹配的任何連接點執行時觸發。
此建議接受一個 ProceedingJointPoint 類型的參數。該參數使我們有機會在目標方法調用之前採取行動。在這種情況下,我們簡單地保存方法開始時間。
其次,建議的返回值類型為 Object,因為目標方法可以返回任何類型的結果。如果目標方法為 void,則返回 null。在目標方法調用後,我們可以測量時間、記錄並返回方法的結果值給調用者。
6. 概述
本文介紹了 Spring 中不同類型的通知及其聲明和實現。我們使用基於模式的方法以及 AspectJ 註解定義了切面。我們還提供了多種可能的通知應用。