We are still cooking the magic in the way!
Creating Your First Aspect
Creating Your First Aspect
Knowing what AOP is in theory is one thing; writing a class that Spring actually treats as an aspect is another. In this lesson you will build a real, runnable aspect from scratch inside a Spring Boot 3 application. By the end you will understand the three essential ingredients — the @Aspect annotation, the @Component annotation, and the auto-proxy infrastructure — and why each one is necessary.
The Three Ingredients
Every Spring aspect needs exactly three things to work:
@Aspect— tells the AspectJ weaver (used by Spring at runtime) that this class carries advice and pointcut definitions.@Component(or any stereotype annotation) — registers the class as a Spring bean so the container can manage it. Without this, Spring never discovers the aspect.- Auto-proxy enabled — the mechanism that intercepts method calls and routes them through matching advice. In Spring Boot this is on by default; in plain Spring you must add one annotation.
@Aspect and @Component? They serve different purposes. @Aspect is an AspectJ marker — it tells the AOP framework how to interpret the class. @Component is a Spring IoC marker — it tells the container to create a bean. Neither implies the other. Forgetting @Component is the most common first-timer mistake; the class compiles fine, but the advice is silently ignored.
Enabling AspectJ Auto-Proxying
Spring AOP works by wrapping target beans in a proxy that intercepts calls and runs matching advice before or after delegating to the real object. The infrastructure that creates these proxies is called the auto-proxy creator, and it is activated by @EnableAspectJAutoProxy.
In a Spring Boot application you do not need to add this annotation yourself. The spring-boot-autoconfigure module includes AopAutoConfiguration, which activates auto-proxying automatically as long as spring-aop is on the classpath. Just add the starter to your build:
That single dependency pulls in both spring-aop and aspectjweaver, which is the AspectJ runtime library that Spring delegates to for pointcut matching. If you are using plain Spring (no Boot), you activate the infrastructure explicitly:
pom.xml or build.gradle before debugging anything else.
Writing the Aspect Class
Let us build a logging aspect that prints a message every time any method in the service layer is called. Here is the minimal skeleton:
Walk through each piece:
@Aspect— marks the class as an aspect. Spring will scan it for@Before,@After,@Around, and other advice annotations.@Component— registers it as a singleton bean in the application context. You could also use@Serviceor@Repository, but@Componentis the most honest choice because an aspect is not a service or a repository — it is cross-cutting infrastructure.@Before("execution(...)")— declares a before advice with an inline pointcut expression. The expression targets every method (any return type*, any name*, any arguments(..)) inside any class in thecom.example.demo.servicepackage.
A Concrete Working Example
Here is the full picture with a real service so you can run and observe the behaviour:
Notice the JoinPoint parameter. Spring injects this automatically whenever you declare it as the first parameter of an advice method. It gives you runtime information about the intercepted call — the target object, the method name, and the arguments. The advice signature does not need to match the target method's signature at all; Spring handles the wiring.
What Happens at Runtime
When the application context starts, the auto-proxy creator scans all bean definitions. When it finds a bean that matches at least one pointcut declared in any @Aspect bean, it wraps that bean in a dynamic proxy. From that point on, every call to the proxied bean goes through the proxy first, which checks whether advice applies to the called method and runs it if so.
For OrderService above, the proxy created by Spring intercepts both placeOrder and cancelOrder. When a controller or another service injects OrderService, it actually receives the proxy, not the raw instance. The proxy is transparent — it implements the same interface or extends the same class — so callers need no changes.
placeOrder calls cancelOrder directly (i.e. this.cancelOrder(...)), the call goes straight to the real object and skips the proxy entirely. The aspect will not fire. This is a fundamental limitation of Spring's proxy-based AOP. The solution is to inject the bean into itself (via @Lazy) or, for complex cases, use full AspectJ compile-time weaving.
Organising Aspects in a Real Project
Keep all aspect classes in a dedicated package such as com.example.demo.aspect. This makes it immediately obvious that a class is cross-cutting infrastructure and not business logic. One aspect class per concern — a LoggingAspect, a SecurityAspect, a PerformanceAspect — scales better than putting all advice into a single giant class. Each aspect should be focused and testable in isolation.
Summary
Creating an aspect in Spring requires @Aspect to identify the class as AOP infrastructure, @Component to register it as a Spring bean, and auto-proxy support (provided automatically by Spring Boot's AOP starter). Advice methods receive an optional JoinPoint parameter that exposes runtime details about the intercepted call. Self-invocation is the one hard limitation to keep in mind. With these fundamentals in place you are ready to explore the full range of advice types in the next lesson.