I am trying to Practice Spring AOP. The Problem is, My program is not what I expect.
It should Look something like this when Aspect works.
Sep 27, 2020 1:11:11 PM aspects.LoggingAspect log
INFO: Method will execute
Sep 27, 2020 1:11:11 PM com.cms.services.CommentService publishComment
INFO: Publishing comment:Demo comment
Sep 27, 2020 1:11:11 PM aspects.LoggingAspect log
INFO: Method executed
However, It doesnt' log. Like Aspects haven't work at all.
com.cms.services.CommentService publishComment
INFO: Publishing Comment: Demo Comment
Main.java executes overall code Using Instance spring Spring Context and also uses CommentService.java.
CommentService.java is nothing but of printing one lined log. It is placed under services package.
Then there is LoggingAspect.java For Aspect Programming.
Finally, CommentConfig.java is for configuring EnableAspectJAutoProxy and registering Beans for Aspect class.
Here is my code.
Main.java
public class Main {
public static void main(String[] args) {
var c = new AnnotationConfigApplicationContext(CommentConfig.class);
var service = c.getBean(CommentService.class);
Comment comment = new Comment();
comment.setText("Demo Comment");
comment.setAuthor("Natasha");
service.publishComment(comment);
}
}
CommentService.java
@Service
public class CommentService {
private Logger logger = Logger.getLogger(CommentService.class.getName());
public void publishComment(Comment comment) {
logger.info("Publishing Comment: " + comment.getText());
}
}
LoggingAspect.java
@Aspect
@Component
public class LoggingAspect {
private Logger logger = Logger.getLogger(LoggingAspect.class.getName());
@Around("execution(* services.*.*(..))")
public void log(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("method will execute");
logger.info("Method will execute");
joinPoint.proceed();
logger.info("Method has executed");
System.out.println("method has executed");
}
}
CommentConfig.java
@Configuration
@ComponentScan(basePackages = {"com.cms"})
@EnableAspectJAutoProxy
public class CommentConfig {
@Bean
public LoggingAspect aspect() {
return new LoggingAspect();
}
}
Also, this is my dependency.
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.24</version>
</dependency>
My Package Name
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─cms
│ │ │ │ Main.java
│ │ │ │
│ │ │ ├─aspect
│ │ │ │ LoggingAspect.java
│ │ │ │
│ │ │ ├─config
│ │ │ │ CommentConfig.java
│ │ │ │
│ │ │ ├─model
│ │ │ │ Comment.java
│ │ │ │
│ │ │ ├─proxies
│ │ │ │ CommentNotificationProxy.java
│ │ │ │ CommentPushNotificationProxyImpl.java
│ │ │ │ EmailCommentNotificationProxyImpl.java
│ │ │ │
│ │ │ ├─repositories
│ │ │ │ CommentRepository.java
│ │ │ │ DBCommentRepositoryImpl.java
│ │ │ │
│ │ │ └─services
│ │ │ CommentService.java
│ │ │
│ │ └─resources
Can't figure out what is missing...
Problem Solved.
The Problem was indeed Because of I omitted the Full package name in the @Around Annotation.
Below code makes what I expected in the beginning.
LoggingAspect.java
@Aspect
@Component
public class LoggingAspect {
private Logger logger = Logger.getLogger(LoggingAspect.class.getName());
@Around("execution(* com.cms.services.*.*(..))") // this is where I missed.
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Object arguments[] = joinPoint.getArgs();
logger.info("Method " + methodName + " with Parameters " +
Arrays.asList(arguments) + " will execute");
Object returnedByMethod = joinPoint.proceed();
logger.info("Method executed and returned " + returnedByMethod);
return returnedByMethod;
}
}
For those who are struggling like me, below documentation will help.
https://docs.spring.io/spring-framework/docs/2.0.x/reference/aop.html
It is about the The AspectJ pointcut expression.
Within
Try with simple modification on LoggingAspect. within matches any join point within classes in packages containing "services".
Around
execution specifically matches method executions of methods defined in classes within the "services" package. You have to specify full package for this. Follow the below code in your case. Your service method should be inside this package com.cms.services