To enable Aspect-Oriented Programming in Spring Boot, first add the required dependency to your pom.xml:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
Here's the complete implementation with all necessary components:
- JournalEntry.java (Domain Object)
package com.example.aopdemo;
public class JournalEntry {
private String date;
private String tags;
private String content;
private String heading;
// Getters and Setters
public String getHeading() { return heading; }
public void setHeading(String heading) { this.heading = heading; }
public String getDate() { return date; }
public void setDate(String date) { this.date = date; }
public String getTags() { return tags; }
public void setTags(String tags) { this.tags = tags; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
}
- JournalService.java (Service Interface)
package com.example.aopdemo;
public interface JournalService {
void createEntry(JournalEntry entry);
void displayEntry(JournalEntry entry) throws Exception;
}
- JournalServiceImpl.java (Service Implemantation)
package com.example.aopdemo;
import org.springframework.stereotype.Service;
@Service
public class JournalServiceImpl implements JournalService {
@Override
public void createEntry(JournalEntry entry) {
System.out.println(entry.getHeading());
}
@Override
public void displayEntry(JournalEntry entry) throws Exception {
System.out.println("Heading: " + entry.getHeading());
System.out.println("Date: " + entry.getDate());
System.out.println("Tags: " + entry.getTags());
System.out.println("Content: " + entry.getContent());
throw new Exception("Test exception");
}
}
- JournalAspect.java (AOP Configuration)
package com.example.aopdemo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class JournalAspect {
@Pointcut("execution(* com.example.aopdemo.JournalServiceImpl.displayEntry(..))")
public void displayPointcut() {}
@Before("displayPointcut() && args(entry)")
public void beforeDisplay(JoinPoint jp, JournalEntry entry) {
System.out.println("AOP - Method Args: " + jp.getArgs()[0].getClass());
System.out.println("AOP - Target Class: " + jp.getTarget().getClass());
}
@After("displayPointcut()")
public void afterDisplay() {
System.out.println("AOP - After method execution");
}
@AfterReturning("displayPointcut()")
public void afterSuccessfulDisplay() {
System.out.println("AOP - After successful execution");
}
@AfterThrowing("displayPointcut()")
public void afterFailedDisplay() {
System.out.println("AOP - After exception thrown");
}
}
- JournalController.java (REST Controller)
package com.example.aopdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/journal")
public class JournalController {
@Autowired
private JournalService journalService;
@PostMapping("/display")
public JournalEntry displayEntry() throws Exception {
JournalEntry entry = new JournalEntry();
entry.setHeading("Building Dreams");
entry.setDate("2023-12-31");
entry.setTags("ambition,technology,future");
entry.setContent("Creating something meaningful...");
journalService.displayEntry(entry);
return entry;
}
}
- MainApplication.java (Spring Boot Starter)
package com.example.aopdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class MainApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
@Bean
public JournalAspect journalAspect() {
return new JournalAspect();
}
}
AOP provides powerful capabilities for cross-cutting concerns like logging and transaction management. The aspect configuration allows intercepting method executions at specific join points with various advice types.