Mastering Spring AOP Pointcut Expressions: A Complete Guide
This article explains the syntax and components of Spring AOP pointcut expressions, demonstrates how to use various pointcut designators such as execution, within, this, target, args, @within, @target, @args, and @annotation, and provides practical code examples with advice types.
Expression Explanation
Environment: Spring Boot 2.3.10
The most commonly used
executionpointcut designator is explained with its full syntax:
<code>execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)</code>modifiers-pattern : optional method modifiers (public, private, protected).
ret-type-pattern : required return type, usually
*for any type.
declaring-type-pattern : optional class pattern.
name-pattern : required method name pattern.
param-pattern : required parameter pattern.
throws-pattern : optional exception pattern.
All parts except the returning type pattern, the name pattern, and the parameters pattern are optional. The returning type pattern determines the method's return type needed for a join point to match. * matches any return type. A fully‑qualified type name matches only that specific return type. The name pattern matches the method name; * can be used as a wildcard. Parameter patterns: () matches no parameters, (..) matches any number, (*) matches one parameter of any type, (* ,String) matches two parameters where the second must be a String .
Spring AOP Supported Pointcut Designators
The following image lists the pointcut designators supported by Spring AOP:
Annotation Class
<code>@Component
public class PersonDAOImpl implements PersonDAO {
private static Logger logger = LoggerFactory.getLogger(PersonDAOImpl.class);
public void save(Person person) {
logger.info("save method invoke...");
}
public Person findById(Integer id) {
logger.info("findById method invoke...");
return new Person(id, "姓名" + new Random().nextInt(10000));
}
public int countPersons() {
logger.info("countPersons method invoke...");
return new Random().nextInt(1000);
}
}
public interface PersonDAO {
void save(Person person);
Person findById(Integer id);
int countPersons();
}</code>Aspect Class
<code>@Aspect
@Component
public class PointcutAspect {
private static Logger logger = LoggerFactory.getLogger(PointcutAspect.class);
@Pointcut("execution(* com.pack.dao..*.*(..))")
private void log() {}
@Around("log()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
logger.info("执行前...");
pjp.proceed();
logger.info("执行后...");
}
}</code>Custom Annotation
<code>@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Pack {}
</code>execution Pointcut
Matches method execution join points.
<code>@Pointcut("execution(* com.pack.dao..*.*(..))")
</code>Matches any method in
com.pack.daopackage or sub‑packages, regardless of return type or parameters.
<code>@Pointcut("execution(com.pack.domain.Person com.pack.dao..*.*(..))")
</code>Matches methods returning
com.pack.domain.Person.
<code>@Pointcut("execution(* com.pack.dao..*.sa*(..))")
</code>Matches method names starting with
sa.
<code>@Pointcut("execution(* com.pack.dao..*.*(com.pack.domain.Person))")
</code>Matches methods whose single parameter type is
Person.
<code>@Pointcut("execution(public * com.pack.dao..*.*(..))")
</code>Matches public methods.
<code>@Pointcut("execution(* com.pack.dao.impl.*.*(..))")
</code>Matches any method in
com.pack.dao.implpackage.
within Pointcut
Limits matching to join points within a specific type.
<code>@Pointcut("within(com.pack..*)")
</code>Matches any method in all classes under
com.packand its sub‑packages.
<code>@Pointcut("within(com.pack.dao.impl.PersonDAOImpl)")
</code>Matches any method in
PersonDAOImplclass.
this Pointcut
Matches when the current AOP proxy object is an instance of the specified type.
<code>@Pointcut("this(com.pack.dao.PersonDAO)")
</code>Matches when the proxy implements
PersonDAO.
<code>@Pointcut("this(com.pack.dao.impl.PersonDAOImpl)")
</code>Requires CGLIB proxy; JDK proxy will not match because the proxy implements the interface, not the concrete class.
Spring AOP proxy configuration:
<code>spring:
aop:
proxy-target-class: false # use JDK dynamic proxies
</code>Setting
falseuses JDK proxies (interface‑based) and may cause weaving failures for
thispointcuts targeting concrete classes. Setting
trueuses CGLIB proxies (class‑based) and enables successful weaving.
target Pointcut
Matches when the target object (the actual bean) is of the specified type.
<code>@Pointcut("target(com.pack.dao.PersonDAO)")
</code>Matches any method where the underlying bean implements
PersonDAO, regardless of proxy type.
args Pointcut
Matches methods whose arguments are of the given type(s).
<code>@Pointcut("execution(* com.pack..*.*(..)) && args(com.pack.domain.Person)")
</code>Matches methods receiving a
Personargument.
<code>@Pointcut("execution(* com.pack..*.*(..)) && args(java.lang.String, ..)")
</code>Matches methods whose first argument is a
String.
@within Pointcut
Matches any method within a class annotated with a specific annotation.
<code>@Pointcut("@within(com.pack.dao.Pack)")
</code>@target Pointcut
Matches methods where the target object carries a specific annotation.
<code>@Pointcut("execution(* com.pack..*.*(..)) && @target(com.pack.dao.Pack)")
</code>@args Pointcut
Matches methods whose arguments are annotated with a specific annotation.
<code>@Pointcut("execution(* com.pack..*.*(..)) && @args(com.pack.dao.Pack)")
</code>@annotation Pointcut
Matches methods that are themselves annotated with a specific annotation.
<code>@Pointcut("@annotation(com.pack.dao.Pack)")
</code>Various Advice Types
Before advice
<code>@Before("log()")
public void deBefore(JoinPoint joinPoint) throws Throwable {}
</code>After returning advice
<code>@AfterReturning(returning = "ret", pointcut = "log()")
public void doAfterReturning(Object ret) throws Throwable {
System.out.println("返回值:" + ret);
}
</code>Result screenshot:
After throwing advice
<code>@AfterThrowing("log()")
public void throwss(JoinPoint jp) {
System.out.println("抛出异常了");
}
</code>After (finally) advice
<code>@After("log()")
public void after(JoinPoint jp) {}
</code>Around advice
<code>@Around("log()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
logger.info("执行前...");
Object result = pjp.proceed();
logger.info("执行后...");
return result;
}
</code>The tutorial concludes the comprehensive overview of Spring AOP pointcut expressions and advice types.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.