[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