Spring AOP - Quick Start
Tags: spring, aop, java
Published: 2022-05-23 00:17:22

Spring AOP allows developers to intercept code that executes before and after methods calls. Aspects enable the modularization of crosscutting concerns such as transaction management, security or logging.

Here are a few key terms that you'll encounter when dealing with AOP.

**Advice**
- _is the action taken by an aspect at a particular joinpoint._

**Joinpoint**
- _is the point at which a method or the handling of an exception occurs._

**Pointcut**
- _an expression language of spring AOP which is basically used to match the target methods to apply the advice._
- _Pointcut expressions can be combined using operators like ||, && and ! but in our example we won't be using this technique_
- _syntax: Advice(" execution(modifiers? return-type declaring-type? method-name(param) throws?) ")_
`@Before("execution(public Integer com.company.service.*.add*(..))")_`


## Example
**0. Structure your packages**
ex: 
_com.company_
_com.company.aop_
_com.company.service_

**1. Add to Maven /pom.xml**

```
<!-- aop dependency -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
```

**2. Create your AOP class and apply annotations**
_com.company.aop.MyCustomAspect_
```
@Aspect  // import from org.aspectj.lang.annotation.Aspect
@Component
public class MyCustomAspect{
   // code goes here..
}
```


**3. Add any of these Advice method into your AOP class** 
Before advice
```
@Before("execution(public Integer com.company.service.*.add*(..))") 
public void beforeLoggingAdd() { 
   System.out.println("### LOG: advice that runs BEFORE the method ###"); 
}
```

After advice
```
@After("execution(public Integer com.company.service.*.add*(..))") 
public void afterLoggingAdd() { 
   System.out.println("### LOG: advice that runs AFTER the method ###"); 
}
```

After Returning advice
_an optional returning="return" can be used to access the return value of the matched method_
```
@AfterReturning(pointcut = "execution(public Integer com.company.service.*.add*(..))", returning = "result") 
public void afterReturningLoggingAdd(Object result) { 
   System.out.println("### LOG: advice that runs AFTER the methods's successful execution ###"); 
   System.out.println("result: " + result.toString()); 
}
```

After Throwing advice
```
@AfterThrowing(pointcut = "execution(public Integer com.company.service.*.add*(..))", throwing = "throwingException") 
public void afterExceptionLoggingAdd(Throwable throwingException) { 
   System.out.println("### LOG: advice that runs after the method (if exception is thrown) ###"); 
   System.out.println("exception: " + throwingException); 
}
```

Around advice
_this advice can perform custom behavior both before and after the method invocation_
```
@Around("execution(public Integer com.company.service.*.add*(..))") 
public Integer aroundLoggingAdd(ProceedingJoinPoint jp) throws Throwable { 
   System.out.println("### LOG: advice that runs BEFORE and AFTER the method ###"); 
   Integer result = (Integer) jp.proceed(); 
   System.out.println("### LOGGING ADD METHOD : AROUND ###"); 
   return result;
}
```

**4. Create a method to execute**
_com.company.service.MyService_
```
@Service
public class MyService {
   public Integer addResource(){
      System.out.println("add method executed!");
      return 0;
   }
}
```

**5. Test your AOP advice**
_com.company.DemoApplication_
```
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }

   @Autowired
   MyService ms;

   @Override
   public void run(String... args) throws Exception {
      ms.addResource();
   }
}
```