[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