[toc]
建議與切入點表達式相關聯,并在切入點匹配的方法執行之前,之后或周圍運行。 切入點表達式可以是對命名切入點的簡單引用,也可以是在適當位置聲明的切入點表達式。
## Before advice
建議在方法開始之前執行,在切面中使用`@Before`注解
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
~~~
如果要在此處使用切點表達式,可以重寫
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
@Before("execution(* com.xyz.myapp.dao.*.*(..))")
public void doAccessCheck() {
// ...
}
}
~~~
## After returning advice
建議在方法正常返回之后執行,使用`@AfterReturning`注解
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class AfterReturningExample {
@AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
~~~
有時候你需要在建議方法體內使用切點的返回值,可以如下
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class AfterReturningExample {
@AfterReturning(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
returning="retVal")
public void doAccessCheck(Object retVal) {
// ...
}
}
~~~
returning的屬性值必須和方法參數名稱一致.參數類型也要和切點返回類型一致,Object符合所有類型.
## After throwing advice
建議在方法拋出異常退出時執行,使用`@AfterThrowing`注解
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
@AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doRecoveryActions() {
// ...
}
}
~~~
通常,需要在建議方法體內處理異常,可以使用屬性`throwing `匹配方法參數
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
@AfterThrowing(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
throwing="ex")
public void doRecoveryActions(DataAccessException ex) {
// ...
}
}
~~~
## After (finally) advice
建議在方法結束之后執行,無論正常還是異常結束.使用注解`@After`,需要考慮正常和異常的返回情況
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
@Aspect
public class AfterFinallyExample {
@After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doReleaseLock() {
// ...
}
}
~~~
## Around advice
最后一個建議是圍繞方法執行,.經常用在線程安全模式下共享數據狀態(如開始和結束的計時器).使用滿足需求的建議即可,不要擴大范圍,如before能滿足需求,就不要用around.
范圍建議,使用注解`@Around`.建議方法的第一個參數必須是`ProceedingJoinPoint`.在建議方法體內執行`ProceedingJoinPoint`的`proceed()`方法會執行切點方法.`proceed()`方法也可能要求傳入`Object[]`作為參數.在`proceed()`方法前后可以寫需要的業務邏輯
~~~java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class AroundExample {
@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
}
~~~
## Advice parameters
spring提供了所有的建議類型--意味著你要在方法簽名上聲明參數而不是使用`Object[]`.
### Access to the current JoinPoint
所有建議方法的第一個參數都是`org.aspectj.lang.JoinPoint`(圍繞建議的參數是`ProceedingJoinPoint`是`JoinPoint`的子類).`JoinPoint`提供了很多實用的方法,如`getArgs()`返回方法的參數,`getThis()`返回代理對象,`getTarget()`返回目標對象,`getSignature()`返回方法聲明,`toString()`打印被建議方法的描述.
### Passing parameters to advice
在`after returning`和`after throwing`處已經知道如何綁定返回結果.為了在建議方法體內使用返回結果,可以使用綁定模式`args`
舉例說明,假設你建議的表達式為dao層的方法,且第一個參數為`Account`對象,在建議只是方法體內要訪問這個對象,如下寫法
~~~java
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
public void validateAccount(Account account) {
// ...
}
~~~
切點表達式的`args(account,..)`部分實現了兩個目標:第一,限定表達式的方法至少有一個參數,且這個參數的類型為`Account`;第二,能夠在建議方法體內通過參數`account `來訪問對象.
另一種寫法,通過聲明切點時提供`Account `作為參數,然后在建議時引用這個聲明的切點,如下:
~~~java
@Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
private void accountDataAccessOperation(Account account) {}
@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
// ...
}
~~~
### Advice parameters and generics
### Determining argument names
### Proceeding with arguments
## Advice ordering
如果有多個建議在同一個接入點執行,會發生什么呢?和AspectJ保持一致,
在接入點之前執行的建議,優先級高的先執行,在接入點之后執行的建議,優先級高的后執行.
控制優先級需要實現`org.springframework.core.Ordered`類,或者使用注解`Order `,底層通過`Ordered.getValue()`來確定優先級.
如果兩個建議在同一個接入點執行,沒有定義優先級,考慮把建議合并到一個建議中,或者重構,每個建議在獨立的切面類中,實現排序.
- 正確打開本書的姿勢
- 第一部分 Core
- 1. Ioc container
- 1.1. Introduction to the Spring IoC container and beans
- 1.2. Container overview
- 1.2.1. Configuration metadata
- 1.2.2. Instantiating a container
- 1.2.3. Using the container
- 1.3. Bean overview
- 1.3.1. Naming beans
- 1.3.2. Instantiating beans
- 1.4. Dependencies
- 1.4.1. Dependency Injection
- 1.4.2. Dependencies and configuration in detail
- 1.4.3. Using depends-on
- 1.4.4. Lazy-initialized beans
- 1.4.5. Autowiring collaborators
- 1.4.6. Method injection
- 1.5 Bean Scopes
- 1.6. Customizing the nature of a bean TODO
- 1.7. Bean definition inheritance TODO
- 1.8. Container Extension Points TODO
- 1.9. Annotation-based container configuration
- 1.9.1. @Required
- 1.9.2. @Autowired
- 1.9.3. Fine-tuning annotation-based autowiring with @Primary
- 1.9.4. Fine-tuning annotation-based autowiring with qualifiers TODO
- 1.9.5. Using generics as autowiring qualifiers TODO
- 1.9.6. CustomAutowireConfigurer TODO
- 1.10. Classpath scanning and managed components
- 1.10.1. @Component and further stereotype annotations
- 1.11. Using JSR 330 Standard Annotations TODO
- 1.12. Java-based container configuration
- 1.12.1. Basic concepts: @Bean and @Configuration
- 1.12.2. Instantiating the Spring container using AnnotationConfigApplicationContext
- 2. Resources
- 2.1. Introduction
- 2.2. The Resource interface
- 2.3. Built-in Resource implementations
- 2.3.1. UrlResource
- 2.3.2. ClassPathResource
- 2.3.3. FileSystemResource
- 2.3.4. ServletContextResource
- 2.3.5. InputStreamResource
- 2.3.6. ByteArrayResource
- 2.4. The ResourceLoader
- 2.5. The ResourceLoaderAware interface
- 2.6. Resources as dependencies
- 2.7. Application contexts and Resource paths
- 2.7.1. Constructing application contexts
- 2.7.2. Wildcards in application context constructor resource paths
- 2.7.3. FileSystemResource caveats
- 3. Validation, Data Binding, and Type Conversion
- 4. Spring Expression Language (SpEL)
- 5. Aspect Oriented Programming with Spring
- 5.1. Introduction
- 5.1.1. AOP concepts
- 5.1.2. Spring AOP capabilities and goals
- 5.1.3. AOP Proxies
- 5.2. @AspectJ support
- 5.2.1. Enabling @AspectJ Support
- 5.2.2. Declaring an aspect
- 5.2.3. Declaring a pointcut
- 5.2.4. Declaring advice
- 5.2.5. Introductions TODO
- 5.2.6. Aspect instantiation models TODO
- 5.2.7. Example
- 5.3. Schema-based AOP support TODO
- 5.4. Choosing which AOP declaration style to use TODO
- 5.5. Mixing aspect types TODO
- 5.6. Proxying mechanisms
- 5.6.1. Understanding AOP proxies
- 5.7. Programmatic creation of @AspectJ Proxies
- 5.8. Using AspectJ with Spring applications
- 5.8.1. Using AspectJ to dependency inject domain objects with Spring
- 5.8.2. Other Spring aspects for AspectJ
- 第二部分 Testing
- 第三部分 Data Access
- 1. Transaction Management
- 1.1. Introduction to Spring Framework transaction management
- 1.2 Advantages of the Spring Framework’s transaction support model
- 1.2.1. Global transactions
- 1.2.2. Local transactions
- 1.2.3. Spring Framework’s consistent programming model
- 1.3. Understanding the Spring Framework transaction abstraction
- 1.4. Synchronizing resources with transactions
- 1.4.1. High-level synchronization approach
- 1.4.2. Low-level synchronization approach
- 1.4.3. TransactionAwareDataSourceProxy
- 1.5. Declarative transaction management
- 1.5.1. Understanding the Spring Framework’s declarative transaction implementation
- 1.5.2. Example of declarative transaction implementation
- 1.5.3. Rolling back a declarative transaction
- 1.5.4. Configuring different transactional semantics for different beans
- 1.5.5. tx:advice元素的 settings
- 1.5.6. Using @Transactional
- 1.5.7. Transaction propagation
- 1.5.8. Advising transactional operations
- 1.5.9. Using @Transactional with AspectJ TODO
- 第四部分 web servlet
- 第五部分 Web Reactive
- 第六部分 Integration
- 第七部分 Languages