Backend Development 7 min read

Why Does My Overridden Spring Aspect Log Twice? Debugging and Fixes

This article explains why a Spring AOP aspect that overrides a parent method logs twice, walks through the debugging process that reveals duplicate advisor creation, and presents two solutions—including a pointcut tweak and upgrading to Spring 6.1.8—to eliminate the redundant logs.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Why Does My Overridden Spring Aspect Log Twice? Debugging and Fixes

1. Problem Reproduction

To improve code reuse and maintainability, a generic abstract aspect class CommonAspect was created to encapsulate common logic such as logging, performance monitoring, and exception handling. Business-specific aspects inherit from this class.

<code>public abstract class CommonAspect {
  @Pointcut("execution(public * com.pack..*.*(..))")
  private void commonPointcut() {}

  @Before("bean(*Service)")
  protected void beforeLog(JoinPoint jp) {
    System.out.println("通用日志记录...");
  }

  @Around("@annotation(monitor)")
  protected Object monitorRun(ProceedingJoinPoint pjp, Monitor monitor) throws Throwable {
    Object ret = null;
    // TODO
    ret = pjp.proceed();
    // TODO
    return ret;
  }
  // other
}</code>

A concrete aspect overrides the logging method:

<code>@Component
@Aspect
public class LogAspect extends CommonAspect {
  @Override
  public void beforeLog(JoinPoint jp) {
    System.out.println("重写日志记录功能");
  }
}</code>

Running the application prints the overridden log message twice:

<code>重写日志记录功能
重写日志记录功能
查询Person对象</code>

2. Analysis

During container startup, Spring parses the @Aspect and retrieves all methods from the aspect class. It finds two methods: the one defined in the parent class and the overridden one in the subclass.

The getAdvisorMethods method returns three methods, two from the parent and one overridden method. Spring then creates an Advisor for each, which explains the duplicate execution because Spring does not check whether the advice method overrides a parent method.

These advisors are later turned into Advice (MethodInterceptor) objects that the proxy invokes.

2. Solution

2.1 Solution 1 – Adjust Pointcut

Add a pointcut to the overridden method that does not match any join point, preventing Spring from creating an advisor for it.

<code>@Before("execution(public * xxxooo())")
@Override
public void beforeLog(JoinPoint jp) {
  System.out.println("重写日志记录功能");
}</code>

After this change the output is:

<code>重写日志记录功能
查询Person对象</code>

Only a single log entry appears.

2.2 Solution 2 – Upgrade Spring

Upgrading to Spring 6.1.8 resolves the issue. The core change is in ReflectiveAspectJAdvisorFactory#getAdvisors , where a check is added to compare the method with the most specific method in the aspect class, filtering out inherited methods.

<code>public class ReflectiveAspectJAdvisorFactory {
  public List<Advisor> getAdvisors(...) {
    List<Advisor> advisors = new ArrayList<>();
    for (Method method : getAdvisorMethods(aspectClass)) {
      // Added check: compare with most specific method
      if (method.equals(ClassUtils.getMostSpecificMethod(method, aspectClass))) {
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
        if (advisor != null) {
          advisors.add(advisor);
        }
      }
    }
  }
}</code>

In versions lower than 6.1.8 this check is absent, so duplicate advisors are created.

debuggingJavaAOPSpringSpringBootAspectJ
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.