Aspect-Oriented Programming (AOP) is a powerful way to separate cross-cutting concerns like logging, security, or transactions from your core business logic. In Micronaut, AOP is implemented using compile-time tools, making it lightweight and fast β perfect for microservices.
In this post, youβll learn how AOP works in Micronaut, especially how to use the @Around
annotation and create custom interceptors.

π What is AOP?
AOP helps you encapsulate behaviors that cut across multiple classes β like:
- Logging
- Security checks
- Caching
- Performance monitoring
- Transaction management
These concerns can be injected at runtime without modifying the business logic itself.
π Micronaut AOP with @Around
Micronaut supports AOP using @Around
and interceptor bindings. These annotations allow you to wrap method execution logic using interceptors.
π¦ Maven Setup
Ensure your Maven project has the following dependencies in your pom.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<dependencies> <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-runtime</artifactId> </dependency> <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-aop</artifactId> </dependency> <dependency> <groupId>jakarta.inject</groupId> <artifactId>jakarta.inject-api</artifactId> </dependency> </dependencies> |
π οΈ Create a Custom Annotation
Weβll start by defining a custom annotation to apply on methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.kscodes.micronaut.advanced; import io.micronaut.aop.Around; import java.lang.annotation.*; @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Around // Micronaut-specific annotation public @interface LogExecutionTime { } |
βοΈ Create the Interceptor
This class will handle logic around the method execution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.kscodes.micronaut.advanced; import io.micronaut.aop.MethodInterceptor; import io.micronaut.aop.MethodInvocationContext; import jakarta.inject.Singleton; @Singleton public class LogExecutionTimeInterceptor implements MethodInterceptor<Object, Object> { @Override public Object intercept(MethodInvocationContext<Object, Object> context) { long start = System.currentTimeMillis(); try { return context.proceed(); // Execute the actual method } finally { long duration = System.currentTimeMillis() - start; System.out.println("Method [" + context.getMethodName() + "] executed in " + duration + "ms"); } } } |
π Micronaut automatically wires this interceptor with your
@LogExecutionTime
annotation.
β¨ Using the Custom Annotation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kscodes.micronaut.advanced; import jakarta.inject.Singleton; @Singleton public class ReportService { @LogExecutionTime public void generateReport() throws InterruptedException { Thread.sleep(500); // Simulate delay System.out.println("Report generated"); } } |
π§ͺ Test the AOP Logic
Create an entry point to call the service and observe the logs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.kscodes.micronaut.advanced; import io.micronaut.runtime.Micronaut; public class Application { public static void main(String[] args) { var context = Micronaut.run(Application.class); ReportService reportService = context.getBean(ReportService.class); try { reportService.generateReport(); } catch (InterruptedException e) { e.printStackTrace(); } } } |
π Real-World Use Cases for AOP in Micronaut
- Logging user actions
- Validating method arguments
- Timing method execution (performance tracking)
- Security permission checks
- Auditing access to APIs
π Tips for Working with AOP in Micronaut
- Always use
@Around
in your custom annotations to enable interception. - Interceptors must be marked with
@Singleton
. - Use
context.proceed()
to ensure the actual method is executed. - Avoid overusing AOPβit should enhance readability, not complicate it.
π Conclusion
Micronaut AOP with @Around
and custom interceptors gives you a powerful tool to cleanly inject behavior into your services. Unlike runtime AOP frameworks, Micronaut does this at compile time, keeping your apps fast and memory-efficient.
This Micronaut AOP tutorial helps you get started with real-world examples, showing how you can monitor and control method behavior without cluttering your business logic.