[toc]
切点声明有两部分:一个是方法名称和参数的签名,一个是切点表达式确定关注哪些执行方法.在@AspectJ 注解风格的aop中,切点表达式使用注解`@Pointcut`,方法必须是`void`1返回类型.
下面例子清楚的区分切点签名和切点表达式.名称为`anyOldTransfer`的切点,匹配执行所有名称为`transfer`的方法.
~~~java
@Pointcut("execution(* transfer(..))")// the pointcut expression
private void anyOldTransfer() {}// the pointcut signature
~~~
## Supported Pointcut Designators
* execution-匹配执行方法的连接点,是spring aop的主要切点指示符
* within - 限制匹配某些类型中的连接点
* this - 限制匹配给定类型的实例中的连接点
* target - 限制匹配给定类型中的连接点
* args - 限制匹配给定参数类型中的连接点
## Combining pointcut expressions
切点表达式可以结合使用 '&&', '||' 和 '!'.也可以引用名称.
~~~java
//匹配所有的public方法
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}
//trading包目录下的所有方法
@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {}
//trading包目录下的所有public方法
@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {}
~~~
如上所示,最佳实践是从较小的命名组件构建更复杂的切入点表达式。
## Sharing common pointcut definitions
企业级应用中,经常需要按模块或特定的操作引用一些切面.为了达到这个目的,建议定义系统架构层的切面,抓住常见的切点表达式.一个典型的切面如下:
~~~java
package com.xyz.someapp;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class SystemArchitecture {
/**
* web层连接点,如果方法定义在
* 包com.xyz.someapp.web package或子包下面类的方法中
*/
@Pointcut("within(com.xyz.someapp.web..*)")
public void inWebLayer() {}
/**
* service层连接点,如果方法定义在
* 包com.xyz.someapp.service package或子包下面类的方法中
*/
@Pointcut("within(com.xyz.someapp.service..*)")
public void inServiceLayer() {}
/**
* dao层,,如果方法定义在
* 包com.xyz.someapp.dao或子包下面类的方法中
*/
@Pointcut("within(com.xyz.someapp.dao..*)")
public void inDataAccessLayer() {}
/**
*具体业务是service接口中任意方法的执行,接口在"service"包,实现类在子包
* 如果按功能划分service接口(例如,com.xyz.someapp.abc.service and com.xyz.someapp.def.service) 则使用切点表达式"execution(* com.xyz.someapp..service.*.*(..))"
*/
@Pointcut("execution(* com.xyz.someapp..service.*.*(..))")
public void businessService() {}
/**
*数据访问层的操作是dao接口的执行,接口定义在包"dao" , a实现类在子包
*/
@Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
public void dataAccessOperation() {}
}
~~~
这样的切面中定义的切点,通过切点表达式可以引用到任何地方.例如service层提供事务,可以这么写:
~~~xml
<aop:config>
<aop:advisor
pointcut="com.xyz.someapp.SystemArchitecture.businessService()"
advice-ref="tx-advice"/>
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
~~~
`<aop:config>` 和 `<aop:advisor>`的用法参考[Schema-based AOP support](https://docs.spring.io/spring/docs/5.0.7.RELEASE/spring-framework-reference/core.html#aop-schema).事务管理参考[Transaction Management](https://docs.spring.io/spring/docs/5.0.7.RELEASE/spring-framework-reference/data-access.html#transaction).
## Examples
spring aop开发者常用的切点指示符是`execution`,完整格式为
~~~
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
~~~
除了返回类型,名称,参数,其他模式都是可选的.返回类型模式限制了连接点方法必须匹配.最常见的是使用`*`作为返回类型模式,它匹配任何返回类型。完全限定类型名称必须匹配方法返回给定类型.名称模式匹配方法名称.可以使用`*`通配完整或部分名称.可以在名称模式末尾加上`.` 指定声明类型模式. 参数模式稍微复杂一些:`()`匹配不带参数的方法,而`(..)`匹配任意数量的参数(零或更多)。 模式`(*)`匹配采用任何类型的一个参数的方法,`(*,String)`匹配采用两个参数的方法,第一个可以是任何类型,第二个必须是String。 有关更多信息,请参阅AspectJ编程指南的语言语义部分。
下面给出一些切点的样例
* 所有public方法
~~~java
execution(public * *(..))
~~~
* 所有set开头的方法
~~~
execution(* set*(..))
~~~
* 接口AccountService的所有方法
~~~
execution(* com.xyz.service.AccountService.*(..))
~~~
* 所有service包下的方法
~~~
execution(* com.xyz.service.*.*(..))
~~~
* 所有service包或子包下的方法
~~~
execution(* com.xyz.service..*.*(..))
~~~
* 所有service包内的类型
~~~
within(com.xyz.service.*)
~~~
* 所有service包或子包下的类型
~~~
within(com.xyz.service..*)
~~~
* 所有实现了接口`AccountService `的代理
~~~
this(com.xyz.service.AccountService)
~~~
* 所有实现了接口`AccountService `的类
~~~
target(com.xyz.service.AccountService)
~~~
* 所有一个参数的方法,且参数类型在运行时为`Serializable`
~~~
args(java.io.Serializable)
~~~
区别于`execution(* *(java.io.Serializable))`表示方法的签名,指定了参数类型.
* 所有使用了注解`@Transactional`的目标类
~~~
@target(org.springframework.transaction.annotation.Transactional)
~~~
* 所有使用了注解`@Transactional`的声明类
~~~
@within(org.springframework.transaction.annotation.Transactional)
~~~
* 所有使用了注解`@Transactional`的执行方法
~~~
@annotation(org.springframework.transaction.annotation.Transactional)
~~~
* 所有一个参数的方法,且参数类型在运行时为注解`@Classified`
~~~
@args(com.xyz.security.Classified)
~~~
* 所有名称为`tradeService`的bean
~~~
bean(tradeService)
~~~
* 所有名称匹配为`*Service`的bean
~~~
bean(*Service)
~~~
## Writing good pointcuts
在编译期间,AspectJ 检查代码,搜索匹配切点表达式的连接点,这是一个耗费性能的过程,所以在定义切点表达式的时候,尽可能精确.
表达式的指示符分为三组:`kinded,scoping和context`
* kinded 类型指示符,选择接入点类型的指示符,如 execution, get, set, call, handler
* Scoping 范围指示符,如within, withincode
* Contextual 上下文指示符是基于上下文匹配的指示符。 例如:this,target,@ annotation
一个写得很好的切入点应该尝试包括至少前两种类型(kinded和scoping),而如果希望基于连接点上下文匹配,则可以包括上下文指示符,或者绑定该上下文以在建议中使用。
- 正确打开本书的姿势
- 第一部分 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