Introduction
Spring Framework remains the standard for enterprise Java applications in 2026. This advanced tutorial guides you through complex concepts like aspect-oriented programming, bean post-processors, and reactive integration. You will learn to structure a modular, testable, and performant application. Each section includes complete, ready-to-use code for real production scenarios.
Prerequisites
- Java 21+
- Maven 3.9+
- Solid knowledge of Spring Core and Boot
- IDE with Spring support (IntelliJ IDEA recommended)
Maven Project Configuration
<?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>com.example</groupId>
<artifactId>advanced-spring</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>This POM includes the essential starters for AOP and web. It ensures compatibility with Spring 6.1+ and avoids dependency conflicts via the parent BOM.
Custom BeanPostProcessor
package com.example.advanced;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Auditable) {
System.out.println("Initialisation de : " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}This post-processor intercepts all beans and applies logic before/after initialization. Useful for auditing or dynamic injection without modifying target classes.
AOP Aspect for Logging
package com.example.advanced;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.advanced.service.*.*(..))")
public void logBeforeMethod() {
System.out.println("Méthode service appelée");
}
}The aspect captures service calls via pointcut. This centralizes cross-cutting logging without polluting business code.
Service with Custom Annotation
package com.example.advanced.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Auditable
public void createUser(String name) {
System.out.println("Utilisateur créé : " + name);
}
}The service uses a custom annotation to mark audited methods. Combined with the BeanPostProcessor, this activates advanced behavior.
Custom Auditable Annotation
package com.example.advanced;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Auditable {
}Simple marker annotation used for detection by the post-processor or aspect. It enables clean declarative configuration.
Best Practices
- Always use precise @ComponentScan annotations to avoid unnecessary scans
- Prefer aspects for cross-cutting concerns
- Document custom BeanPostProcessors
- Use Spring profiles for environments
- Write integration tests with @SpringBootTest
Common Mistakes to Avoid
- Forgetting @EnableAspectJAutoProxy which disables aspects
- Creating beans with new() instead of the Spring context
- Ignoring bean lifecycles in post-processors
- Not handling exceptions in aspects
Further Reading
Deepen your knowledge with our complete courses at learni-group.com/formations.