Spring AOP AspectJ @Around Annotation Example

This Spring AOP tutorial will teach us to use AspectJ @Around annotation. Unlike @Before and @After annotations, the @Around allows us to fully control the method execution, providing the opportunity to modify the input, alter the return value, or even skip the target method altogether.

The @Around annotation wraps the execution of a target or advised method with custom logic. Conceptually, it is similar to proxy the target class and invoking the advised method using the proxy.

1. AspectJ @Around Annotation Usage

To leverage the @Around annotation, use it on a method within the aspect. The method accepts a parameter of type ProceedingJoinPoint. In the advice, call proceed() on the ProceedingJoinPoint to invoke the actual method.

If we do not invoke the ProceedingJoinPoint.proceed() then the original method will be executed.

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Around("execution(* com.howtodoinjava.core.aop.service.EmployeeService.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {

        // Custom logic before the method execution
        logger.info("Before method execution");

        // Proceed with the actual method execution
        Object result = joinPoint.proceed();

        // Custom logic after the method execution
        logger.info("After method execution");

        return result;
    }
}

We should the @Around annotation when we need complete control over the method execution, including modification of input, output, or even skipping the method invocation.

The equivalent XML configuration is:

<!-- Enable AspectJ auto proxy -->
<aop:aspectj-autoproxy />

<!-- Define the aspect -->
<bean id="loggingAspect" class="com.example.aspect.LoggingAspect" />

<!-- Configure the aspect and pointcut -->
<aop:config>
    <aop:aspect id="aroundAspect" ref="loggingAspect">
        <aop:pointcut id="aroundPointcut"
                      expression="execution(* com.howtodoinjava.core.aop.service.EmployeeService.*(..))" />
        <aop:around method="aroundAdvice" pointcut-ref="aroundPointcut" />
    </aop:aspect>
</aop:config>

2. Handling Exceptions

We must ensure that the @Around advice handles exceptions appropriately using try-catch blocks. If an exception is caught, decide whether to propagate, log, or handle it within the advice.

try {
  // Proceed with the actual method execution
  Object result = joinPoint.proceed();
} catch (Exception ex) {
  log.error("Exception caught during method execution: " + ex.getMessage());
  // Decide whether to propagate, log, or handle the exception
  return handleException(ex);
}

Also, consider using try-with-resources or finally blocks to manage resources effectively, especially when interacting with external systems or acquiring resources.

3. Demo

When we run any method in the class com.howtodoinjava.core.aop.service.EmployeeService then we can see that the aroundAdvice() is executed after it is completed.

import com.howtodoinjava.core.demo.beans.Employee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class EmployeeService {

  private static final Logger logger = LoggerFactory.getLogger(EmployeeService.class);

  public Employee save(Employee employee) {
    logger.info("Saving the Employee...");
    return null;
  }
}

Let’s run a method and verify the output.

import com.howtodoinjava.core.aop.service.EmployeeService;
import com.howtodoinjava.core.demo.beans.Employee;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

    EmployeeService employeeService = context.getBean(EmployeeService.class);
    employeeService.save(new Employee());

    context.close();
  }
}

The program output is:

2023-11-27T13:34:13.205+0530 INFO Before method execution
2023-11-27T13:34:13.206+0530 INFO Saving the Employee...
2023-11-27T13:34:13.207+0530 INFO After method execution

4. Maven

To get the @After annotation working, we need to ensure that Spring AOP is setup correctly. So make sure we have the following dependencies:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>6.1.1</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>6.1.1</version>
</dependency>

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.20</version>
</dependency>

5. Enabling AOP

Also, we must enable the AOP support to @Aspect annotation to work.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class AppConfig {
  //...
}

6. Conclusion

The @Around annotation in Spring AOP with AspectJ allows for the implementation of complex cross-cutting concerns. We should use it carefully as simple mistakes in the advice code can prevent the advised method

Happy Learning !!

Soure Code on Github

Comments

Subscribe
Notify of
guest
1 Comment
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode