How to Build a Custom Spring Boot Starter that Logs Method Execution Time

Learn how to create a custom Spring Boot starter named aspectlog-spring-boot-starter that automatically logs method execution times using AOP, covering project setup, Maven configuration, conditional loading, annotation definition, auto‑configuration class, META‑INF registration, and packaging for reuse in other projects.

Programmer DD
Programmer DD
Programmer DD
How to Build a Custom Spring Boot Starter that Logs Method Execution Time

Introduction

If you use Spring Boot, you will inevitably work with various spring-boot-starter modules. Creating a simple starter that logs method execution time only requires four steps.

Step 1 – Create a Maven Project

Starter projects follow a naming convention: spring-boot-starter-XX for official starters and XX-spring-boot-starter for third‑party extensions. Our starter will be named aspectlog-spring-boot-starter.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>aspectlog-spring-boot-starter</artifactId>
    <version>1.0.2</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.15.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

The spring-boot-configuration-processor dependency lets Spring collect auto‑configuration conditions into META-INF/spring-autoconfigure-metadata.properties, improving startup time.

Step 2 – Write Auto‑Configuration Logic

2.1 Define the @AspectLog Annotation

package com.shanyuan.autoconfiguration.aspectlog;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AspectLog {
}

2.2 Define Configuration Properties

package com.shanyuan.autoconfiguration.aspectlog;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("aspectLog")
public class AspectLogProperties {
    private boolean enable;
    public boolean isEnable() { return enable; }
    public void setEnable(boolean enable) { this.enable = enable; }
}

2.3 Define the Auto‑Configuration Class

package com.shanyuan.autoconfiguration.aspectlog;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.PriorityOrdered;

@Aspect
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
@Configuration
@ConditionalOnProperty(prefix = "aspectLog", name = "enable", havingValue = "true", matchIfMissing = true)
public class AspectLogAutoConfiguration implements PriorityOrdered {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Around("@annotation(com.shanyuan.autoconfiguration.aspectlog.AspectLog)")
    public Object isOpen(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        String taskName = thisJoinPoint.getSignature().toString()
                .substring(thisJoinPoint.getSignature().toString().indexOf(" "),
                           thisJoinPoint.getSignature().toString().indexOf("("))
                .trim();
        long time = System.currentTimeMillis();
        Object result = thisJoinPoint.proceed();
        logger.info("method:{} run :{} ms", taskName, (System.currentTimeMillis() - time));
        return result;
    }

    @Override
    public int getOrder() {
        // Ensure transaction and other aspects run first
        return Integer.MAX_VALUE;
    }
}

The @ConditionalOnProperty ensures the configuration is activated only when aspectLog.enable=true (or the property is missing, defaulting to true).

Step 3 – Register in META‑INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.shanyuan.autoconfiguration.aspectlog.AspectLogAutoConfiguration

This file tells Spring Boot to load the auto‑configuration class automatically.

Step 4 – Package and Test

After building the project with mvn install, include the generated JAR as a dependency in other Spring Boot applications. The starter will log execution time for any method annotated with @AspectLog when the property is enabled.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

aopSpring Bootmethod timingCustom Starter
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

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.