Backend Development 7 min read

Mastering Spring AOP: Control Flow Pointcuts & Introduction Advice Explained

This tutorial walks through Spring AOP's control flow pointcuts and introduction advice, showing how to define dynamic pointcuts, create advisors, and use @DeclareParents to add interfaces to beans, complete with practical code examples and output analysis.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring AOP: Control Flow Pointcuts & Introduction Advice Explained

1. Introduction

Spring AOP is a core part of the Spring framework that allows developers to define cross‑cutting concerns such as logging, transaction management, and security. Two key features—control flow pointcuts and introduction advice—enhance maintainability and readability of applications.

Control Flow Pointcut

A control flow pointcut lets you define a join point based on the runtime call stack. It matches when a method is invoked from a specific class or method, using org.springframework.aop.support.ControlFlowPointcut .

Introduction Advice

Introduction advice (via @DeclareParents ) declares that a target bean should implement a given interface and provides a default implementation, enabling you to add new behavior without modifying the original class.

2. Practical Example

2.1 Control Flow Pointcut

Prepare base classes:

<code>@Component
public class PersonDAO {
  public void save(String name) {
    System.out.println("PersonDAO save method invoke...");
  }
}

@Component
public class PersonService {
  @Resource
  private PersonDAO dao;
  public void save(String name) {
    System.out.println("PersonService save method inovke...");
    this.dao.save(name);
  }
}
</code>

Define the low‑level advisor (the actual Advisor that Spring creates from an @Aspect ):

<code>@Component
public class PackControlFlowAdvisor extends DefaultPointcutAdvisor {
  private static MethodInterceptor logInterceptor = invocation -> {
    System.out.println("before log...");
    Object ret = invocation.proceed();
    System.out.println("after log...");
    return ret;
  };
  private static Class<?> clazz = PersonService.class;
  private static String methodName = "save";
  private static ControlFlowPointcut pointcut = new ControlFlowPointcut(clazz, methodName);
  public PackControlFlowAdvisor() {
    super(pointcut, logInterceptor);
  }
}
</code>

Test code:

<code>PersonService ps = context.getBean(PersonService.class);
ps.save("王五");
</code>

Console output:

<code>PersonService save method inovke...
before log...
PersonDAO save method invoke...
after log...
</code>

The ControlFlowPointcut matches because the call stack of PersonService.save contains the configured class and method, causing the PersonDAO.save method to be intercepted.

2.2 Introduction Advice

Define an interface and its default implementation:

<code>// Interface to be introduced
public interface CommonManager {
  void calc(int a, int b);
}

// Default implementation
public class DefaultCommonManager implements CommonManager {
  @Override
  public void calc(int a, int b) {
    System.out.printf("计算a + b = %d%n", a + b);
  }
}

// Target class that will gain the interface
@Component("us")
public class UserService {
  public void save() {
    System.out.println("UserService save...");
  }
}
</code>

Aspect that introduces the interface:

<code>@Aspect
public static class CommonAspect {
  /**
   * All classes matching the value pattern will automatically implement
   * CommonManager, using DefaultCommonManager as the default implementation.
   */
  @DeclareParents(value = "com.pack.main.aop_introductionadviser.IntructionDeclareMain2.*+", defaultImpl = DefaultCommonManager.class)
  public static CommonManager mixin;
}
</code>

Test code:

<code>CommonManager c = (CommonManager) context.getBean("us");
c.calc(10, 20);
</code>

Console output:

<code>计算a + b = 30
</code>

The UserService bean is proxied to implement CommonManager , and calls to calc are delegated to DefaultCommonManager .

Summary: Control flow pointcuts and introduction advice are powerful Spring AOP concepts. The former lets you intercept code based on runtime call‑stack conditions, while the latter enables dynamic interface implementation, both enhancing modularity when used judiciously.

JavaSpring AOPAspectJControl Flow PointcutIntroduction Advice
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.