6 Using aspects with Spring AOP
This chapter introduces aspect-oriented programming as a way to keep cross-cutting concerns, such as logging, security, auditing, timing, and transaction handling, separate from core business logic. Rather than repeating the same supporting code across many methods, you define it once as an aspect and let Spring apply it where needed. This makes application code easier to read and maintain, and it also helps explain how important Spring features are built under the hood.
To use aspects in Spring, you enable proxy-based aspect support, register the aspect class as a Spring bean, and define advice that tells Spring when and where to intercept method calls. Spring weaves the aspect by wrapping the target bean in a proxy, so calls go through the proxy first. With an around advice, the aspect can run code before and after the method, delegate to the original method with proceed(), inspect method names and arguments, and even alter the values passed in or returned to the caller. The chapter also shows a cleaner approach for selecting methods by using a custom annotation and matching it with an annotation-based pointcut.
The chapter also covers alternative advice types for simpler needs, including before, after returning, after throwing, and after advice. Finally, it explains that multiple aspects can form an execution chain, where the order of interception matters, especially when one aspect may prevent the method from running at all. Spring can control that order with an ordering annotation, letting you decide which concern runs first. Overall, the chapter emphasizes using aspects carefully: they are powerful, but they should hide only truly irrelevant details and never make important behavior harder to understand.
Sometimes it’s not relevant to have parts of the code in the same place as the business logic because it makes the app more difficult to understand. A solution is to move part of the code aside from the business logic implementation using aspects. In this scene, Jane, the programmer, is discouraged by the logging lines written together with the business code. Count Dracula shows her the magic of aspects by decoupling the logs into an aspect.
The aspect terminology: Spring executes some logic (the aspect) when someone calls a specific method (the pointcut). We need to specify when the logic is executed according to the pointcut (e.g., before). The when is the advice. For Spring to intercept the method, the object that defines the intercepted method needs to be a bean in the Spring context. So, the bean becomes the target object of the aspect.
Weaving an aspect. Instead of giving you a reference to the real bean, Spring gives you a reference to a proxy object, intercepts the method calls, and manages the aspect logic.
When a method isn’t aspected, the call goes directly to that method. When we define an aspect for a method, the call goes through the proxy object. The proxy object applies the logic defined by the aspect and then delegates the call to the real method.
To implement an aspect, you follow four easy steps. First, you need to enable the aspect capability in your app. Then you create an aspect class, define a method, and instruct Spring when and what to intercept. Finally, you implement the aspect logic.
The AspectJ pointcut expression used in the example. It tells Spring to intercept the calls for all the methods in the services package, regardless of their return type, the class they belong to, name, or the parameters they receive.
The aspect behavior: LoggingAspect wraps the method execution by displaying something before and after the method call. This way, you observe a simple implementation of an aspect.
If you don’t call the proceed() method of the ProceedingJoinPoint parameter of the aspect, the aspect never delegates further to the intercepted method. In this case, the aspect simply executes instead of the intercepted method. The caller of the method doesn’t know that the real method is never executed.
An aspect can decide not to delegate at all to the method it intercepts. This behavior looks like the aspect applies a mind trick to the caller of the method. The caller ends up executing another logic than the one it called.
The aspect intercepts the method call, so it can access the parameters and the value returned by the intercepted method after execution. For the main() method, it looks like it directly calls the publishComment() method of the CommentService bean. The caller isn’t aware that an aspect intercepted the call.
An aspect can change the parameters used to call the intercepted method and the returned value received by the intercepted method’s caller. This approach is powerful, and it gives flexible control of the intercepted method.
The steps for intercepted annotated methods. You need to create a custom annotation you want to use to annotate the methods your aspect needs to intercept. Then you use a different AspectJ pointcut expression to configure the aspect to intercept the methods annotated with the custom annotation you created.
Using an AspectJ pointcut expression, we weave the aspect logic to any method annotated with the custom annotation we defined. This is a comfortable way to mark the methods to which specific aspect logic applies.
The aspect execution order matters. Depending on your app’s requirements, you need to choose a specific order for the aspects to execute. In this scenario, the LoggingAspect cannot log all the method executions if the SecurityAspect executes first.
The execution flow. The LoggingAspect was first to intercept the method call. The LoggingAspect delegates further in the execution chain to the SecurityAspect, which further delegates the call to the intercepted method. The intercepted method returns to the SecurityAspect, which returns further to the LoggingAspect.
The execution flow after changing the order of the aspects. The SecurityAspect was first to intercept the method call and delegates further in the execution chain to the LoggingAspect, which further delegates the call to the intercepted method. The intercepted method returns to the LoggingAspect, which returns further to the SecurityAspect.
Summary
- An aspect is an object that intercepts a method call and can execute logic before, after, and even instead of executing the intercepted method. This helps you decouple part of the code from the business implementation and makes your app easier to maintain.
- Using an aspect, you can write logic that executes with a method execution while being completely decoupled from that method. This way, someone who reads the code only sees what’s relevant regarding the business implementation.
- However, aspects can be a dangerous tool. Overengineering your code with aspects will make your app less maintainable. You don’t need to use aspects everywhere. When using them, make sure they really help your implementation.
- Aspects support many essential Spring capabilities like transactions and securing methods.
- To define an aspect in Spring, you annotate the class implementing the aspect logic with the @Aspect annotation. But remember that Spring needs to manage an instance of this class, so you need to also add a bean of its type in the Spring context.
- To tell Spring which methods an aspect needs to intercept, you use AspectJ pointcut expressions. You write these expressions as values to advice annotations. Spring offers you five advice annotations: @Around, @Before, @After, @AfterThrowing, and @AfterReturning. In most cases we use @Around, which is also the most powerful.
- Multiple aspects can intercept the same method call. In this case, it’s recommended that you define an order for the aspects to execute using the @Order annotation.
Spring Start Here, Second Edition ebook for free