This project is based on chapter 6.2. Implementing aspects with Spring AOP from book Spring Starts here (2021) by Laurentiu Spilca.
File > New project > Java
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.1.10</version> </dependency>@Service public class MessageService { // create logger private Logger logger = Logger.getLogger(MessageService.class.getName()); // log message public void processMessage(final String message) { logger.info("Processing message: " + message); } }@Configuration @ComponentScan(basePackages = "org.example") public class ApplicationConfiguration { }<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>6.1.10</version> </dependency>@Configuration + @EnableAspectJAutoProxy @ComponentScan(basePackages = "org.example") public class ApplicationConfiguration { }- use
@Aspectannotation to mark bean as aspect
@Aspect @Component public class LoggingAspect { }-
explanation of the pointcut expression in
@Aroundannotation:-
*- this wildcard symbol indicates any return type of the method. It means the advice applies regardless of what the method returns. -
org.example.MessageService- This is the fully qualified name of the class containing the method to be advised. It specifies that the target method is within the MessageService class in the org.example package. -
processMessage- this is the name of the method to be advised. The advice will be applied to methods with this name. -
(..)- these parentheses with two dots inside signify any number and type of arguments to the method. It means the advice applies to processMessage methods regardless of what parameters they take.
-
@Aspect @Component public class LoggingAspect { private Logger logger = Logger.getLogger(LoggingAspect.class.getName()); @Around("execution(* org.example.MessageService.processMessage(..))") public Object log(ProceedingJoinPoint joinPoint) throws Throwable { logger.info("Before processing message"); Object result = joinPoint.proceed(); logger.info("After processing message"); return result; } }@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ArgumentsLog { }@Aspect @Component public class ArgumentsAspect { private Logger logger = Logger.getLogger(ArgumentsAspect.class.getName()); @Before("@annotation(ArgumentsLog)") public void logArguments(JoinPoint joinPoint) { final String methodName = joinPoint.getSignature().getName(); final Object [] arguments = joinPoint.getArgs(); logger.info("Method " + methodName + " with parameters " + Arrays.asList(arguments) + " will execute"); } }@Service public class MessageService { private Logger logger = Logger.getLogger(MessageService.class.getName()); + @ArgumentsLog public void processMessage(final String message) { logger.info("Processing message: " + message); } }ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);MessageService messageService = context.getBean(MessageService.class);messageService.processMessage("Hello World!");<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.11.0-M2</version> <scope>test</scope> </dependency>public class ApplicationTests { @Test @DisplayName("Checks that Application Context is created") public void checkApplicationContextCreated() { ApplicationContext context = new AnnotationConfigApplicationContext(); assertNotNull(context); } }