Skip to content

Pointcut designators (execution, this, target, within, args) in Spring AOP

1. Overview

In this article, we will go through the various pointcut designators (execution, this, target, within, args) supported in the Spring AOP. Let’s look at the basic key terminologies before we move forward.

1.1. Key Terminologies

Join Point: A point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, it always represents the method execution.

Advice: An Action to be taken before, after, or around a particular join point or method execution. The different advice types include “around,” “before” and “after” advice.

Pointcut in Spring AOP: A predicate that matches join points. It is a set of one or more join points (method executions) for which the Advice executes.

Pointcut expression: An expression language that helps to match the target methods to apply the advice.

2. Pointcut designators

A pointcut expression contains a pointcut designator and a pattern to match the method executions. Let’s see an example to understand this.

@Pointcut("execution(* transfer(..))") 

In the above example, execution is the pointcut designator whereas “* transfer(..)” is the pattern enclosed within the braces.

2.1. execution AOP

This is the primary pointcut designator and helps to match the method execution join points. See this article Pointcut expressions to know more about various patterns supported by this execution designator.

2.2. within AOP

Within AOP limits matching to join points within certain types.

@Pointcut("within(com.tedblob.model..*")
private void withinModelAll() {}

The above expression limits the method executions within the com.tedblob.model package (type) and its sub-packages.

@Pointcut("within(com.tedblob.model.*")
private void withinModel() {}

This expression limits the method executions within the com.tedblob.model package.

2.3 @within AOP

@within limits matching to join points or method executions within types that have the given annotation.

 @Pointcut("@within(com.tedblob.annotations.Secured)")
 public void securedClassPointcut() {
 }

This pointcut matches all the methods inside the class annotated with @Secured.

@Secured
public class Security {
    
    public String getSecurityAlgorithm() {
        return algorithm;
    }

    public int getSecurityScore() {
        return securityScore;
    }
}

securedClassPointcut matches all the methods (getSecurityAlgorithm, getSecurityScore) inside this Security class.

2.4. args AOP

Args limits matching to join points or method executions where the arguments are instances of the given types.

args(java.io.Serializable)

This expression matches the methods with a single parameter and where the argument passed at runtime is Serializable.

Now, let’s see the difference between execution and args.

execution(* *(java.io.Serializable))

Here, the execution expression matches any method with a single parameter of type Serializable class (doesn’t support sub-classes that implement Serializable) whereas args matches if the argument passed at runtime is Serializable. So args can accept a class that implements Serializable class (sub-class) or Serializable class.

2.5. @args AOP

@args limits matching to join points or method executions where the runtime type of the actual arguments passed have annotations of the provided type(s). Let’s see an example to understand this.

CountryCode is an enum annotated with custom annotation @Country. The mentioned countryPointcut with @args matches the method executions with a single argument having annotation @Country.

getCountryCode method has a single argument CountryCode annotated with @Country. So countryPointcut matches the getCountryCode method execution and will execute after that.

 @Pointcut("@args(com.tedblob.annotations.Country)")
 public void countryPointcut() {
 }

 @After("countryPointcut()")
 public void afterCountryAdvice(JoinPoint joinPoint) {
    System.out.println("After - countryPointcut" + joinPoint.getSignature().getName());
 }
 
@Retention(RUNTIME)
public @interface Country {
}

@Country
public enum CountryCode {
    US, UK, IN, JA
}
 public String getCountryCode(CountryCode countryCode) {
    return countryCode;
 }

2.6 @annotation AOP

@annotation limits matching to method executions where the method has the given annotation.

@Pointcut("@annotation(com.tedblob.annotations.Validation)")
public void validationPointcut() {
}
 @Validation
 public boolean validateInput(String input) {
    return false;
 }

The above validationPointcut matches the methods which have the annotation @Validation. So, validateInput method will be matched.

2.7 this and target

this limits matching to join points (the method executions) where the bean reference (Spring AOP proxy) is an instance of the given type.

target limits matching to join points (the method executions) where the target object (application object being proxied) is an instance of the given type.

Let’s recall the JDK dynamic proxy and CGLIB proxy mechanisms to get a grasp of these concepts.

2.7.1. this and target for JDK Dynamic proxy

The Spring AOP is proxy-based. Consider the target class implements at least one interface, then Spring uses JDK dynamic proxy to create a proxy object for the target class. The proxy object extends the same interface and proxies all the interface methods. The calls to the overridden methods of the target class will go to the proxy object first and the proxy object will delegate to all the advice declared for the target class.

The below target class CountriesRepositoryImpl implements an interface. Spring uses Jdk dynamic proxy here and creates a proxy object which also implements the same interface.

@Component
public class CountriesRepositoryImpl implements CountryRepository {
    @Override
    public List<String> getCountries() {
       return countries;
    }
}
package com.tedbob.aspects;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class CurrenciesRepositoryAspect {

	@Before("target(com.tedbob.bls.CountryRepository)")
	public void beforeTargetCountriesRepository() {
	    System.out.println("beforeCountriesRepository");
	}

    @After("this(com.tedbob.bls.CountryRepository)")
	public void afterCountriesRepository() {
	    System.out.println("afterCountriesRepository");
	}

}

Target designator matches the target object which is of type com.tedblob.interface.CountryRepository. Here, the beforeTargetCountriesRepository advice matches the target class CountriesRepositoryImpl.

This designator matches the proxy object which is of type com.tedblob.interface.CountryRepository. Since the proxy object of CountryRepositoryImpl also implements the same interface CountryRepository, this advice executes.

2.7.1. this and target for CGLIB proxy

You can use @EnableAspectJAutoProxy(proxyTargetClass=true) annotation in your class to prevent the Jdk dynamic proxy. Also, if your target class doesn’t implement any interface, then Spring uses CGLIB proxy and creates a proxy object that will be a subclass of your target class.

@Component
public class CountriesRepositoryImpl {
    public List<String> getCountries() {
       return countries;
    }
}

Here, this designator matches the proxy object of type CountriesRepositoryImpl. As the proxy object is a subclass of CountriesRepositoryImpl, this advice executes whenever any call happens to the CountriesRepositoryImpl.

@Before("his(com.tedblob.interface.CountriesRepositoryImpl)")
public void beforeThisCountriesRepository() {
    System.out.println("beforeThisCountriesRepository");
}

The below target designator won’t work in this scenario as the target object doesn’t implement any interface and not instance of any other type. “Exception in thread “main” org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘com.tedbob.interface.CountryRepository’ available” compilation error thrown.

@Before("target(com.tedblob.interface.CountryRepository)")
public void beforeTargetCountriesRepository() {
    System.out.println("beforeCountriesRepository");
}

Consider the below scenario where the target class has the annotation @EnableAspectJAutoProxy(proxyTargetClass=true) to use CGLIB proxy and implements an interface. The target designator works here because the target object is of type CountryRepository.

@Component
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class CountriesRepositoryImpl implements CountryRepository {
    
	public int getCountriesCount() {
        return 0;
    }
}

package com.tedbob.aspects;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class CurrenciesRepositoryAspect {

	@Before("target(com.tedbob.bls.CountryRepository)")
	public void beforeTargetCountriesRepository() {
	    System.out.println("beforeCountriesRepository");
	}

    @After("this(com.tedbob.bls.CountriesRepositoryImpl)")
	public void afterCountriesRepository() {
	    System.out.println("afterCountriesRepository");
	}

    @Around("this(com.tedbob.bls.CountryRepository)")
	public int aroundCountriesRepository(ProceedingJoinPoint joinPoint) throws Throwable {
	    System.out.println("aroundCountriesRepository");
    	return (int) joinPoint.proceed();
	}
}

3. Conclusion

In this article, we have seen various pointcut designators and their use cases.

3 thoughts on “Pointcut designators (execution, this, target, within, args) in Spring AOP”

  1. Pingback: Pointcut in Spring AOP - TedBlob

  2. Pingback: Pointcut expression in Spring AOP (various pointcut patterns) - TedBlob

  3. Pingback: What is the JoinPoint argument used for? - TedBlob

Leave a Reply

Your email address will not be published. Required fields are marked *