Pointcuts and Wildcard Expressions


Pointcut:- Advice means what and when but point cut mean where. Pointcut Means where we exexute the advice. Where out aspect will be run that is pointcut.

Pointcut is A predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP: Spring uses the AspectJ pointcut language by default.

Recall that pointcuts determine join points of interest, and thus enable us to control when advice executes. Spring AOP only supports method execution join points for Spring beans, so you can think of a pointcut as matching the execution of methods on Spring beans. A pointcut declaration has two parts: a signature comprising a name and any parameters, and a pointcut expression that determines exactly which method executions we are interested in. In the @AspectJ annotation-style of AOP, a pointcut signature is provided by a regular method definition, and the pointcut expression is indicated using the @Pointcut annotation (the method serving as the pointcut signature must have a void return type).


An example will help make this distinction between a pointcut signature and a pointcut expression clear. The following example defines a pointcut named 'anyOldTransfer' that will match the execution of any method named 'transfer':
@Pointcut("execution(* transfer(..))")// the pointcut expression
private void anyOldTransfer() {}// the pointcut signature

Supported Pointcut Designators

Spring AOP supports the following AspectJ pointcut designators (PCD) for use in pointcut expressions:
  • execution - for matching method execution join points, this is the primary pointcut designator you will use when working with Spring AOP
  • within - limits matching to join points within certain types (simply the execution of a method declared within a matching type when using Spring AOP)
  • this - limits matching to join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type
  • target - limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type
  • args - limits matching to join points (the execution of methods when using Spring AOP) where the arguments are instances of the given types
  • @target - limits matching to join points (the execution of methods when using Spring AOP) where the class of the executing object has an annotation of the given type
  • @args - limits matching to join points (the execution of methods when using Spring AOP) where the runtime type of the actual arguments passed have annotations of the given type(s)
  • @within - limits matching to join points within types that have the given annotation (the execution of methods declared in types with the given annotation when using Spring AOP)
  • @annotation - limits matching to join points where the subject of the join point (method being executed in Spring AOP) has the given annotation

Combining pointcut expressions

Pointcut expressions can be combined using '&&', '||' and '!'. It is also possible to refer to pointcut expressions by name. The following example shows three pointcut expressions: anyPublicOperation (which matches if a method execution join point represents the execution of any public method); inTrading (which matches if a method execution is in the trading module), and tradingOperation (which matches if a method execution represents any public method in the trading module).
@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

When working with enterprise applications, you often want to refer to modules of the application and particular sets of operations from within several aspects. We recommend defining a "SystemArchitecture" aspect that captures common pointcut expressions for this purpose. A typical such aspect would look as follows:
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.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() {}

}
The pointcuts defined in such an aspect can be referred to anywhere that you need a pointcut expression. For example, to make the service layer transactional, you could write:
<aop:config>
  <aop:advisor advice-ref="tx-advice" pointcut="com.xyz.someapp.SystemArchitecture.businessService()">
</aop:advisor></aop:config>

<tx:advice id="tx-advice">
  <tx:attributes>
    <tx:method name="*" propagation="REQUIRED">
  </tx:method></tx:attributes>
</tx:advice>
Some examples of common pointcut expressions are given below.
  • the execution of any public method:
    execution(public * *(..))
  • the execution of any method with a name beginning with "set":
    execution(* set*(..))
  • the execution of any method defined by the AccountService interface:
    execution(* com.xyz.service.AccountService.*(..))
  • the execution of any method defined in the service package:
    execution(* com.xyz.service.*.*(..))
  • the execution of any method defined in the service package or a sub-package:
    execution(* com.xyz.service..*.*(..))
  • any join point (method execution only in Spring AOP) within the service package:
    within(com.xyz.service.*)
  • any join point (method execution only in Spring AOP) within the service package or a sub-package:
    within(com.xyz.service..*)
  • any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:
    this(com.xyz.service.AccountService)
    'this' is more commonly used in a binding form :- see the following section on advice for how to make the proxy object available in the advice body.
  • any join point (method execution only in Spring AOP) where the target object implements the AccountService interface:
    target(com.xyz.service.AccountService)
    'target' is more commonly used in a binding form :- see the following section on advice for how to make the target object available in the advice body.
  • any join point (method execution only in Spring AOP) which takes a single parameter, and where the argument passed at runtime is Serializable:
    args(java.io.Serializable)
    'args' is more commonly used in a binding form :- see the following section on advice for how to make the method arguments available in the advice body.
    Note that the pointcut given in this example is different to execution(* *(java.io.Serializable)): the args version matches if the argument passed at runtime is Serializable, the execution version matches if the method signature declares a single parameter of type Serializable.
  • any join point (method execution only in Spring AOP) where the target object has an @Transactional annotation:
    @target(org.springframework.transaction.annotation.Transactional)
    '@target' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
  • any join point (method execution only in Spring AOP) where the declared type of the target object has an @Transactional annotation:
    @within(org.springframework.transaction.annotation.Transactional)
    '@within' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
  • any join point (method execution only in Spring AOP) where the executing method has an @Transactional annotation:
    @annotation(org.springframework.transaction.annotation.Transactional)
    '@annotation' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.
  • any join point (method execution only in Spring AOP) which takes a single parameter, and where the runtime type of the argument passed has the @Classified annotation:
    @args(com.xyz.security.Classified)
    '@args' can also be used in a binding form :- see the following section on advice for how to make the annotation object(s) available in the advice body.
  • any join point (method execution only in Spring AOP) on a Spring bean named 'tradeService':
    bean(tradeService)
  • any join point (method execution only in Spring AOP) on Spring beans having names that match the wildcard expression '*Service':
    bean(*Service)





No comments:

Post a Comment