Spring FrameWork Core Tech

The IoC Container 5. PonitCut定义方

2019-03-04  本文已影响0人  小鲍比大爷

在前一章讲解了注解方式的定义的AOP基本使用方式,在本节讲解下AOP的@PointCut表达式的多种写法(本质还是AspectJ表达式语法)。

Supported Pointcut Designators
以下是Spring所支持的表达式标识符(AspectJ标识符的子集)。Pointcut Designator简称PCD。

Spring AOP还额外支持的PCD 为bean标识符,可以通过指定bean name来过滤bean:

bean(idOrNameOfBean)

Combining Pointcut Expressions
PointCut表达式可以通过&&, || 和 ! 运算符组合。
tradingOperation为anyPublicOperation和inTrading表达式组合后的结果,tradingOperation的过滤结果等于anyPublicOperation与inTrading过滤结果的交集。这样我们在指定切点表达式时,可以通过组合的方式复用过滤条件,所以切点的条件表达式定义的越细越好,从而使其他切点表达式定义可以直接复用。

@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {} 

@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {} 

@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {} 

Sharing Common Pointcut Definitions
可以通过划分模块的方式,将一些切点定义放在同一个类中,比如SystemArchitecture,使用的时候直接引用该切点即可。(再重复下,@PointCut表达式会过滤出所有符合条件的类的方法)。

package com.xyz.someapp;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SystemArchitecture {

    /**
     * A join point is in the web layer if the method is defined
     * in a type in the com.xyz.someapp.web package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.someapp.web..*)")
    public void inWebLayer() {}

    /**
     * A join point is in the service layer if the method is defined
     * in a type in the com.xyz.someapp.service package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.someapp.service..*)")
    public void inServiceLayer() {}

    /**
     * A join point is in the data access layer if the method is defined
     * in a type in the com.xyz.someapp.dao package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.someapp.dao..*)")
    public void inDataAccessLayer() {}

    /**
     * A business service is the execution of any method defined on a service
     * interface. This definition assumes that interfaces are placed in the
     * "service" package, and that implementation types are in sub-packages.
     *
     * If you group service interfaces by functional area (for example,
     * in packages com.xyz.someapp.abc.service and com.xyz.someapp.def.service) then
     * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
     * could be used instead.
     *
     * Alternatively, you can write the expression using the 'bean'
     * PCD, like so "bean(*Service)". (This assumes that you have
     * named your Spring service beans in a consistent fashion.)
     */
    @Pointcut("execution(* com.xyz.someapp..service.*.*(..))")
    public void businessService() {}

    /**
     * A data access operation is the execution of any method defined on a
     * dao interface. This definition assumes that interfaces are placed in the
     * "dao" package, and that implementation types are in sub-packages.
     */
    @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
    public void dataAccessOperation() {}

}

execution表达式格式

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
            throws-pattern?)

后面带问号的为可选,不带问号是必选。modifiers-pattern就是public这些修饰符;ret-type-pattern为需要匹配的返回值,经常也用来表示匹配任意返回类型;name-pattern表示方法名,也可以用表示匹配任意方法名;declaring-type-pattern表示类型名(即方法所在的类),declaring-type-pattern用 . 连接name-pattern;(param-pattern)代表方法入参,()表示为无参方法,(..)表示0个或多个参数,()代表单个参数的方法,但是可以匹配任意类型,(,String)表示两个参数的方法,第一个参数类型任意,第二个参数为String类型。具体语法,可以参考AspectJ语法文档

Examples

execution(public * *(..))
execution(* set*(..))
execution(* com.xyz.service.AccountService.*(..))
execution(* com.xyz.service.*.*(..))
execution(* com.xyz.service..*.*(..))
within(com.xyz.service.*)
within(com.xyz.service..*)
this(com.xyz.service.AccountService)
target(com.xyz.service.AccountService)
args(java.io.Serializable)

Note that the pointcut given in this example is different from execution(* *(java.io.Serializable)). The args version matches if the argument passed at runtime is Serializable, and the execution version matches if the method signature declares a single parameter of type Serializable.

@target(org.springframework.transaction.annotation.Transactional)
@within(org.springframework.transaction.annotation.Transactional)
@annotation(org.springframework.transaction.annotation.Transactional)
@args(com.xyz.security.Classified)
bean(tradeService)
bean(*Service)

Writing Good Pointcuts
如何写出好的PointCuts:

For optimal performance of matching, you should think about what they are trying to achieve and narrow the search space for matches as much as possible in the definition.

一般通过定制更严格的限定条件,尽可能的narrow切点的搜索空间。
AspectJ的PCD包含以下几种(Spring AOP只支持前面提到过的几种):

@PointCut表达式的好的写法至少包含前两种PCD:Kinded designators和Scoping designators。

上一篇 下一篇

猜你喜欢

热点阅读