Spring Boot AOP Basics: Implement Logging, Transactions, and Permission Checks

This article introduces Aspect‑Oriented Programming in Spring Boot, explains core AOP concepts and terminology, and provides step‑by‑step code examples for creating logging, transaction management, and permission‑validation aspects using annotations such as @Aspect, @Around, @Before, and @Transactional.

Java Tech Workshop
Java Tech Workshop
Java Tech Workshop
Spring Boot AOP Basics: Implement Logging, Transactions, and Permission Checks

AOP (Aspect‑Oriented Programming) is one of the two core features of Spring and a must‑know technique for enterprise development. It allows developers to add cross‑cutting functionality—such as logging, transaction handling, permission checks, performance monitoring, and duplicate‑submission protection—without modifying the original business code.

What is AOP and why use it?

AOP stands for Aspect Oriented Programming. In simple terms, it lets you "sneak" code in before or after a method execution, keeping the business logic untouched.

Many concerns are generic across all interfaces: logging every request, opening a transaction for every method, validating permissions, and monitoring execution time. Writing these repeatedly leads to code explosion, redundancy, and maintenance difficulty. AOP lets you write the logic once and apply it globally.

AOP Core Terminology

Aspect : the functionality to be added (e.g., logging, permission).

Advice : when to add the functionality (before, after, on exception).

Pointcut : which methods to target.

JoinPoint : the target method execution point.

Weaving : the process of injecting the functionality into the method.

Five Types of Advice

@Before – runs before the method.

@After – runs after the method regardless of outcome.

@AfterReturning – runs after a normal return.

@AfterThrowing – runs after an exception is thrown.

@Around – the most powerful and commonly used; wraps the method execution.

Dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Simple Logging Aspect

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/** AOP logging aspect */
@Slf4j
@Aspect
@Component
public class LogAspect {
    // Pointcut: all Controller methods
    @Pointcut("execution(* com.demo.controller.*.*(..))")
    public void logPointcut() {}

    // Before advice: log before execution
    @Before("logPointcut()")
    public void beforeLog() {
        log.info("✅ Interface execution started…");
    }
}

When the application starts, every interface automatically prints a log entry.

Interface Logging with @Around

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Slf4j
@Aspect
@Component
public class ApiLogAspect {
    @Pointcut("execution(* com.demo.controller.*.*(..))")
    public void apiLog() {}

    @Around("apiLog()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. Get method name
        String methodName = joinPoint.getSignature().getName();
        log.info("🔍 Interface execution: {}", methodName);
        // 2. Get parameters
        Object[] args = joinPoint.getArgs();
        log.info("🔍 Interface args: {}", Arrays.toString(args));
        // 3. Timing start
        long start = System.currentTimeMillis();
        // 4. Execute target method
        Object result = joinPoint.proceed();
        // 5. Calculate elapsed time and log result
        long time = System.currentTimeMillis() - start;
        log.info("✅ Interface return: {}", result);
        log.info("⏱ Interface elapsed: {}ms", time);
        return result;
    }
}

Transaction Management via AOP

Spring transactions are themselves implemented with AOP. Adding a single @Transactional annotation automatically commits on normal return and rolls back on exception. @Transactional Example:

@Service
public class UserService {
    @Transactional(rollbackFor = Exception.class)
    public void addUser(User user) {
        // two-step operation: both must succeed or both fail
        userMapper.insert(user);
        logMapper.insert("新增用户");
    }
}

Custom Permission Annotation and Aspect

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 RequirePermission {
    String value(); // permission code
}
@Aspect
@Component
public class PermissionAspect {
    @Around("@annotation(requirePermission)")
    public Object checkPermission(ProceedingJoinPoint joinPoint, RequirePermission requirePermission) throws Throwable {
        // 1. Required permission
        String permission = requirePermission.value();
        // 2. Current user permission (from Redis/ThreadLocal)
        String userPermission = getUserPermission();
        // 3. Verify
        if (!permission.equals(userPermission)) {
            throw new BusinessException(403, "无权限访问");
        }
        // 4. Proceed
        return joinPoint.proceed();
    }
}

Usage example:

@GetMapping("/user/list")
@RequirePermission("user:list")
public Result<List<User>> userList() {
    return Result.success(userService.list());
}

Pointcut Expressions

// Match all Controllers
execution(* com.xxx.controller.*.*(..))
// Match methods annotated with @Transactional
@annotation(org.springframework.transaction.annotation.Transactional)
// Match all Services
execution(* com.xxx.service.*.*(..))

AOP Execution Order

@Around before → @Before → target method → @AfterReturning / @AfterThrowing → @After → @Around after

Summary

AOP = add functionality without modifying code, applied globally.

@Aspect + @Component define an aspect.

@Around is the most powerful advice type.

Three practical scenarios: interface logging, transaction management, permission validation.

Enterprise‑essential concerns—logging, permission, transaction, monitoring, rate limiting—are all handled via AOP.

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.

TransactionAOPPermissionLoggingspring-bootAspectJ
Java Tech Workshop
Written by

Java Tech Workshop

Focused on Java backend technologies, sharing fundamentals, multithreading, JVM, the Spring ecosystem, microservices, distributed systems, high concurrency, source‑code analysis, and practical experience. Continuously delivers high‑quality original content, interview guides, and learning roadmaps to help Java developers progress from beginner to advanced, enhancing technical skills and core competitiveness.

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.